[Libreoffice-commits] core.git: Branch 'feature/mar-updater' - 856 commits - accessibility/inc accessibility/source android/Makefile android/source animations/source autogen.sh avmedia/source basctl/source basegfx/source basegfx/test basic/qa basic/source binaryurp/source bin/update bridges/source canvas/source chart2/qa chart2/source cli_ure/readme.txt cli_ure/source codemaker/source comphelper/qa comphelper/source compilerplugins/clang compilerplugins/Makefile-clang.mk config_host/config_features.h.in config_host.mk.in configure.ac connectivity/source cppcanvas/qa cppcanvas/source cppuhelper/source cppu/qa cui/Library_cui.mk cui/source cui/uiconfig dbaccess/source dbaccess/UIConfig_dbaccess.mk desktop/CppunitTest_desktop_app.mk desktop/inc desktop/Library_crashreport.mk desktop/Library_sofficeapp.mk desktop/qa desktop/source dictionaries download.lst drawinglayer/source dtrans/source editeng/qa editeng/source embeddedobj/source eventattacher/source extensions/qa extensions/source extensions/tes t extensions/workben external/boost external/libxmlsec extras/source filter/source filter/uiconfig forms/source formula/source fpicker/inc fpicker/source fpicker/test framework/inc framework/Library_fwk.mk framework/Library_fwl.mk framework/qa framework/source helpcompiler/inc helpcompiler/source helpcontent2 hwpfilter/source i18nlangtag/source i18npool/CustomTarget_breakiterator.mk i18npool/source icon-themes/breeze icon-themes/breeze_dark icon-themes/breeze_svg icon-themes/elementary icon-themes/galaxy icon-themes/tango idlc/source idl/source include/basic include/comphelper include/desktop include/editeng include/filter include/formula include/framework include/LibreOfficeKit include/o3tl include/onlineupdate include/oox include/osl include/registry include/sal include/sfx2 include/svl include/svtools include/svx include/toolkit include/tools include/touch include/ucbhelper include/unotools include/vbahelper include/vcl include/xmloff ios/experimental io/source io/test javaunohel per/source jurt/Library_jpipe.mk l10ntools/source libreofficekit/qa libreofficekit/source lingucomponent/source linguistic/source linguistic/workben lotuswordpro/source Makefile.gbuild Makefile.in mysqlc/source odk/examples offapi/com offapi/type_reference officecfg/files.mk officecfg/registry onlineupdate/astyle.options onlineupdate/CustomTarget_generated.mk onlineupdate/Executable_mar.mk onlineupdate/Executable_mbsdiff.mk onlineupdate/Executable_updater.mk onlineupdate/Executable_update_service.mk onlineupdate/inc onlineupdate/Module_onlineupdate.mk onlineupdate/README onlineupdate/source onlineupdate/StaticLibrary_libmar.mk onlineupdate/StaticLibrary_updatehelper.mk onlineupdate/StaticLibrary_winhelper.mk onlineupdate/WinResTarget_updater.mk oovbaapi/ooo oox/inc oox/source opencl/source package/source postprocess/CustomTarget_images.mk postprocess/CustomTarget_registry.mk postprocess/CustomTarget_signing.mk postprocess/Rdb_services.mk pyuno/source qadevOOo/runner qadevOOo/tests r eadlicense_oo/license README.cross registry/tools remotebridges/source reportbuilder/java reportdesign/inc reportdesign/source Repository.mk rsc/inc rsc/source sal/osl sal/qa sal/rtl sal/textenc sax/qa sax/source sax/test scaddins/source sc/inc sc/Library_sc.mk sc/Library_scui.mk scp2/inc scp2/source sc/qa scripting/source sc/sdi sc/source sc/uiconfig sdext/source sd/inc sd/Library_sd.mk sd/qa sd/sdi sd/source setup_native/Library_getuid.mk sfx2/inc sfx2/Library_sfx.mk sfx2/qa sfx2/sdi sfx2/source shell/qa shell/source slideshow/source solenv/bin solenv/gbuild solenv/Module_solenv.mk sot/source starmath/inc starmath/sdi starmath/source starmath/uiconfig starmath/UIConfig_smath.mk stoc/source stoc/test store/source svgio/inc svgio/source svl/source svtools/inc svtools/source svx/inc svx/sdi svx/source svx/uiconfig sw/CppunitTest_sw_txtexport.mk sw/inc sw/Library_msword.mk sw/Library_sw.mk sw/Module_sw.mk sw/qa sw/sdi sw/source sw/uiconfig sw/UIConfig_swriter.mk sysui/desktop test/sou rce toolkit/source tools/qa tools/source translations ucbhelper/source ucb/source udkapi/com uitest/writer_tests unotools/source unoxml/source uui/source vbahelper/source vcl/CppunitTest_vcl_pdfexport.mk vcl/headless vcl/inc vcl/ios vcl/osx vcl/qa vcl/source vcl/unx vcl/win vcl/workben winaccessibility/source wizards/com writerfilter/qa writerfilter/source writerperfect/source xmlhelp/source xmlhelp/util xmloff/inc xmloff/README xmloff/source xmlscript/source xmlsecurity/inc xmlsecurity/Library_xsec_gpg.mk xmlsecurity/qa xmlsecurity/source xmlsecurity/util

Markus Mohrhard markus.mohrhard at googlemail.com
Thu May 18 23:54:47 UTC 2017


Rebased ref, commits from common ancestor:
commit d70be75765185fc5a9a6fef259db3abebea43a72
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 14:05:28 2017 +0200

    Wsometimes-uninitialized
    
    Change-Id: Ia160685694a386358506f94c4cc1510e5e2a6f62

diff --git a/onlineupdate/source/mbsdiff/bsdiff.cxx b/onlineupdate/source/mbsdiff/bsdiff.cxx
index ef80bd99770f..d455bf98046d 100644
--- a/onlineupdate/source/mbsdiff/bsdiff.cxx
+++ b/onlineupdate/source/mbsdiff/bsdiff.cxx
@@ -212,9 +212,9 @@ search(int32_t *I,unsigned char *old,int32_t oldsize,
 int main(int argc,char *argv[])
 {
     int fd;
-    unsigned char *old,*newbuf;
-    int32_t oldsize,newsize;
-    int32_t *I,*V;
+    unsigned char *old = nullptr,*newbuf = nullptr;
+    int32_t oldsize = 0,newsize = 0;
+    int32_t *I = nullptr,*V = nullptr;
 
     int32_t scan,pos,len;
     int32_t lastscan,lastpos,lastoffset;
commit 1ddefd5e2ddeca55cb264504726810ce31de4baf
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 14:03:07 2017 +0200

    Wunused-macros
    
    Change-Id: Ib50bd405101acb908831d943d449c3cf86b2ac85

diff --git a/onlineupdate/source/update/updater/archivereader.cxx b/onlineupdate/source/update/updater/archivereader.cxx
index ec043680c27e..bb548b919a0b 100644
--- a/onlineupdate/source/update/updater/archivereader.cxx
+++ b/onlineupdate/source/update/updater/archivereader.cxx
@@ -25,7 +25,9 @@
 #endif
 #endif
 
+#if defined(_WIN32)
 #define UPDATER_NO_STRING_GLUE_STL
+#endif
 #include "nsVersionComparator.h"
 #undef UPDATER_NO_STRING_GLUE_STL
 
commit 8db6f6e28ba947be31c0a581b631615e16bd85f8
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 13:58:02 2017 +0200

    remove the newly unused files with old cert verification data
    
    Change-Id: I9753197bcfbff1aaf9bb6ee292d65a356075348f

diff --git a/onlineupdate/source/update/updater/primaryCert.h b/onlineupdate/source/update/updater/primaryCert.h
deleted file mode 100644
index e46af0b59814..000000000000
--- a/onlineupdate/source/update/updater/primaryCert.h
+++ /dev/null
@@ -1,4 +0,0 @@
-const uint8_t primaryCertData[] =
-{
-    0x30, 0x82, 0x02, 0xc3, 0x30, 0x82, 0x01, 0xab, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, 0xa7, 0x67, 0xe2, 0xee, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x3
 0, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb3, 0x63, 0x91, 0x44, 0xf6, 0xf1, 0xd7, 0x7f, 0xc9, 0x3d, 0xee, 0x39, 0x44, 0xba, 0xd5, 0x1b, 0x68, 0x10, 0xfd, 0x2e, 0xb3, 0xe9, 0x17, 0xd8, 0x78, 0x18, 0xff, 0xbb, 0x63, 0x6f, 0x21, 0xd9, 0xb3, 0x55, 0x83, 0xe2, 0x90, 0x18, 0xba, 0x1e, 0x3b, 0x57, 0xbb, 0x4a, 0xc7, 0x4a, 0x3b, 0x49, 0x14, 0x1b, 0xe0, 0xc5, 0x01, 0x8e, 0xb3, 0xfc, 0xe0, 0x31, 0x21, 0xea, 0x6b, 0xc6, 0x5f, 0x70, 0x3c, 0x1f, 0x40, 0x9e, 0x6f, 0xf1, 0x37, 0xa0, 0x74, 0xc5, 0x55, 0xc7, 0x4d, 0x9c, 0xdd, 0x6b, 0xb4, 0xd3, 0x17, 0x22, 0x9e, 0x27, 0xea, 0x57, 0x45, 0x58, 0x19, 0x39, 0x18, 0x42, 0x37, 0x94, 0x8d, 0x11, 0xa1, 0xa9, 0xcb, 0xdd, 0x45, 0x7e, 0x82, 0xbf, 0x93, 0x75, 0xcc, 0x8d, 0x95, 0x04, 0x74, 0xc0, 0x84, 0x2e, 0x7d, 0xbc, 0x56, 0x2d, 0xd1, 0x0e, 0x2e, 0xbf, 0x0e, 0x52, 0x22, 0x0c, 0x65, 0xb2, 0x7a, 0x12, 0x14, 0x27, 0x0b, 0xc9, 0x37, 0x30, 0x48, 0xbc, 0xf0, 0xb8, 0x6d, 0x6f, 0x38, 0xda, 0x98, 0xd0, 0x1c, 0x87, 0xfe, 0x69, 0xc4, 0xc7, 0x73, 0xed, 0x78, 0x01
 , 0xa5, 0xea, 0x48, 0x08, 0x28, 0xcc, 0x0e, 0x52, 0x20, 0x1f, 0x46, 0x42, 0x83, 0x2e, 0xa6, 0xfd, 0x30, 0xc6, 0x48, 0x55, 0x78, 0xff, 0xd6, 0xac, 0xdd, 0x61, 0xd3, 0xb9, 0xdb, 0x49, 0x6b, 0x93, 0x5a, 0x5b, 0x37, 0xf5, 0xcb, 0x09, 0x4a, 0x6c, 0xa3, 0x85, 0x1f, 0xeb, 0x33, 0x3f, 0xd0, 0xda, 0x55, 0xc3, 0xb2, 0x56, 0x7d, 0x13, 0x16, 0x23, 0x2b, 0x1c, 0x3f, 0xdd, 0x1a, 0xf9, 0x90, 0xf7, 0x43, 0x63, 0x80, 0xa5, 0x71, 0xce, 0x23, 0x56, 0x1b, 0xbf, 0x51, 0x3a, 0xfe, 0x6b, 0x48, 0xfd, 0x42, 0x50, 0xc0, 0x09, 0x30, 0x32, 0x27, 0x20, 0x0d, 0xda, 0x32, 0x02, 0x23, 0x92, 0x10, 0x85, 0xbf, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0xb2, 0x3f, 0x45, 0x2c, 0xf5, 0x75, 0xeb, 0x20, 0x2f, 0x76, 0x6f, 0x18, 0x06, 0x42, 0x20, 0x83, 0x39, 0x50, 0x64, 0x07, 0xbb, 0xb1, 0x38, 0x74, 0xbe, 0xbb, 0xf4, 0x25, 0x11, 0x72, 0xf9, 0x4a, 0xf0, 0x9a, 0x0b, 0xe7, 0x45, 0x22, 0x59, 0x04, 0x7b, 0xa4,
  0xe8, 0x46, 0xe5, 0x67, 0xdb, 0x9a, 0x9e, 0x27, 0x94, 0x5e, 0x60, 0x8b, 0xf5, 0xb1, 0x3f, 0xf2, 0xab, 0x1c, 0x54, 0xc8, 0xbc, 0x2b, 0x83, 0xf9, 0xa7, 0x18, 0x02, 0xb6, 0x95, 0xfa, 0xde, 0x16, 0x49, 0xca, 0xbd, 0x2e, 0xfc, 0xb6, 0x36, 0x9a, 0x9a, 0x7a, 0x1f, 0xc8, 0x91, 0xce, 0x30, 0xe2, 0x89, 0x58, 0x05, 0xee, 0xf3, 0xd1, 0xed, 0x79, 0x45, 0x20, 0xbd, 0x84, 0x48, 0xb0, 0x56, 0x8e, 0x04, 0xc8, 0xb7, 0x7e, 0x46, 0x2a, 0x2e, 0xb3, 0xca, 0xc1, 0xb6, 0x0b, 0xd4, 0x31, 0x6e, 0x83, 0x13, 0xe9, 0xa5, 0xbd, 0x17, 0x0e, 0x47, 0x34, 0x99, 0xc9, 0x5b, 0xb2, 0x53, 0x73, 0x57, 0xeb, 0x30, 0x0d, 0x2d, 0xaa, 0x25, 0xbb, 0xab, 0xac, 0xe8, 0xda, 0xf0, 0xf1, 0xd7, 0x2d, 0x17, 0x70, 0x9e, 0x30, 0x3c, 0x38, 0x59, 0xbf, 0x40, 0x3f, 0x6e, 0xe4, 0x22, 0x84, 0x94, 0x59, 0xf6, 0x32, 0xc1, 0xcb, 0x9c, 0x56, 0x52, 0x04, 0xeb, 0xf6, 0xa3, 0x75, 0xf8, 0xcb, 0xed, 0xaf, 0x17, 0x57, 0x8f, 0x98, 0x56, 0xa4, 0x9d, 0x85, 0x16, 0xc8, 0xf7, 0xd6, 0x97, 0xed, 0xab, 0xe0, 0x4c, 0x1a, 0x44, 0x5c, 0x68, 0x30, 0x26, 0x40, 
 0x6b, 0xe9, 0x88, 0x6a, 0x37, 0x1e, 0xbf, 0x25, 0x38, 0x55, 0xd9, 0x84, 0x8d, 0x55, 0x08, 0xe6, 0x18, 0xc3, 0xd7, 0x96, 0xfa, 0xd0, 0x2f, 0x17, 0x9b, 0xb6, 0x40, 0xc3, 0x47, 0xb3, 0x30, 0x01, 0x59, 0xec, 0x7c, 0x8d, 0x7e, 0x0a, 0x0d, 0xeb, 0xc4, 0x3b, 0x06, 0x4e, 0x97, 0x41, 0x5e
-};
diff --git a/onlineupdate/source/update/updater/secondaryCert.h b/onlineupdate/source/update/updater/secondaryCert.h
deleted file mode 100644
index 66e684bd133b..000000000000
--- a/onlineupdate/source/update/updater/secondaryCert.h
+++ /dev/null
@@ -1,4 +0,0 @@
-const uint8_t secondaryCertData[] =
-{
-    0x30, 0x82, 0x02, 0xc3, 0x30, 0x82, 0x01, 0xab, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x00, 0xa7, 0x67, 0xe2, 0xee, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x33, 0x30, 0x30, 0x30, 0x33, 0x31, 0x30, 0x35, 0x5a, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x3
 0, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb3, 0x63, 0x91, 0x44, 0xf6, 0xf1, 0xd7, 0x7f, 0xc9, 0x3d, 0xee, 0x39, 0x44, 0xba, 0xd5, 0x1b, 0x68, 0x10, 0xfd, 0x2e, 0xb3, 0xe9, 0x17, 0xd8, 0x78, 0x18, 0xff, 0xbb, 0x63, 0x6f, 0x21, 0xd9, 0xb3, 0x55, 0x83, 0xe2, 0x90, 0x18, 0xba, 0x1e, 0x3b, 0x57, 0xbb, 0x4a, 0xc7, 0x4a, 0x3b, 0x49, 0x14, 0x1b, 0xe0, 0xc5, 0x01, 0x8e, 0xb3, 0xfc, 0xe0, 0x31, 0x21, 0xea, 0x6b, 0xc6, 0x5f, 0x70, 0x3c, 0x1f, 0x40, 0x9e, 0x6f, 0xf1, 0x37, 0xa0, 0x74, 0xc5, 0x55, 0xc7, 0x4d, 0x9c, 0xdd, 0x6b, 0xb4, 0xd3, 0x17, 0x22, 0x9e, 0x27, 0xea, 0x57, 0x45, 0x58, 0x19, 0x39, 0x18, 0x42, 0x37, 0x94, 0x8d, 0x11, 0xa1, 0xa9, 0xcb, 0xdd, 0x45, 0x7e, 0x82, 0xbf, 0x93, 0x75, 0xcc, 0x8d, 0x95, 0x04, 0x74, 0xc0, 0x84, 0x2e, 0x7d, 0xbc, 0x56, 0x2d, 0xd1, 0x0e, 0x2e, 0xbf, 0x0e, 0x52, 0x22, 0x0c, 0x65, 0xb2, 0x7a, 0x12, 0x14, 0x27, 0x0b, 0xc9, 0x37, 0x30, 0x48, 0xbc, 0xf0, 0xb8, 0x6d, 0x6f, 0x38, 0xda, 0x98, 0xd0, 0x1c, 0x87, 0xfe, 0x69, 0xc4, 0xc7, 0x73, 0xed, 0x78, 0x01
 , 0xa5, 0xea, 0x48, 0x08, 0x28, 0xcc, 0x0e, 0x52, 0x20, 0x1f, 0x46, 0x42, 0x83, 0x2e, 0xa6, 0xfd, 0x30, 0xc6, 0x48, 0x55, 0x78, 0xff, 0xd6, 0xac, 0xdd, 0x61, 0xd3, 0xb9, 0xdb, 0x49, 0x6b, 0x93, 0x5a, 0x5b, 0x37, 0xf5, 0xcb, 0x09, 0x4a, 0x6c, 0xa3, 0x85, 0x1f, 0xeb, 0x33, 0x3f, 0xd0, 0xda, 0x55, 0xc3, 0xb2, 0x56, 0x7d, 0x13, 0x16, 0x23, 0x2b, 0x1c, 0x3f, 0xdd, 0x1a, 0xf9, 0x90, 0xf7, 0x43, 0x63, 0x80, 0xa5, 0x71, 0xce, 0x23, 0x56, 0x1b, 0xbf, 0x51, 0x3a, 0xfe, 0x6b, 0x48, 0xfd, 0x42, 0x50, 0xc0, 0x09, 0x30, 0x32, 0x27, 0x20, 0x0d, 0xda, 0x32, 0x02, 0x23, 0x92, 0x10, 0x85, 0xbf, 0xa1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0xb2, 0x3f, 0x45, 0x2c, 0xf5, 0x75, 0xeb, 0x20, 0x2f, 0x76, 0x6f, 0x18, 0x06, 0x42, 0x20, 0x83, 0x39, 0x50, 0x64, 0x07, 0xbb, 0xb1, 0x38, 0x74, 0xbe, 0xbb, 0xf4, 0x25, 0x11, 0x72, 0xf9, 0x4a, 0xf0, 0x9a, 0x0b, 0xe7, 0x45, 0x22, 0x59, 0x04, 0x7b, 0xa4,
  0xe8, 0x46, 0xe5, 0x67, 0xdb, 0x9a, 0x9e, 0x27, 0x94, 0x5e, 0x60, 0x8b, 0xf5, 0xb1, 0x3f, 0xf2, 0xab, 0x1c, 0x54, 0xc8, 0xbc, 0x2b, 0x83, 0xf9, 0xa7, 0x18, 0x02, 0xb6, 0x95, 0xfa, 0xde, 0x16, 0x49, 0xca, 0xbd, 0x2e, 0xfc, 0xb6, 0x36, 0x9a, 0x9a, 0x7a, 0x1f, 0xc8, 0x91, 0xce, 0x30, 0xe2, 0x89, 0x58, 0x05, 0xee, 0xf3, 0xd1, 0xed, 0x79, 0x45, 0x20, 0xbd, 0x84, 0x48, 0xb0, 0x56, 0x8e, 0x04, 0xc8, 0xb7, 0x7e, 0x46, 0x2a, 0x2e, 0xb3, 0xca, 0xc1, 0xb6, 0x0b, 0xd4, 0x31, 0x6e, 0x83, 0x13, 0xe9, 0xa5, 0xbd, 0x17, 0x0e, 0x47, 0x34, 0x99, 0xc9, 0x5b, 0xb2, 0x53, 0x73, 0x57, 0xeb, 0x30, 0x0d, 0x2d, 0xaa, 0x25, 0xbb, 0xab, 0xac, 0xe8, 0xda, 0xf0, 0xf1, 0xd7, 0x2d, 0x17, 0x70, 0x9e, 0x30, 0x3c, 0x38, 0x59, 0xbf, 0x40, 0x3f, 0x6e, 0xe4, 0x22, 0x84, 0x94, 0x59, 0xf6, 0x32, 0xc1, 0xcb, 0x9c, 0x56, 0x52, 0x04, 0xeb, 0xf6, 0xa3, 0x75, 0xf8, 0xcb, 0xed, 0xaf, 0x17, 0x57, 0x8f, 0x98, 0x56, 0xa4, 0x9d, 0x85, 0x16, 0xc8, 0xf7, 0xd6, 0x97, 0xed, 0xab, 0xe0, 0x4c, 0x1a, 0x44, 0x5c, 0x68, 0x30, 0x26, 0x40, 
 0x6b, 0xe9, 0x88, 0x6a, 0x37, 0x1e, 0xbf, 0x25, 0x38, 0x55, 0xd9, 0x84, 0x8d, 0x55, 0x08, 0xe6, 0x18, 0xc3, 0xd7, 0x96, 0xfa, 0xd0, 0x2f, 0x17, 0x9b, 0xb6, 0x40, 0xc3, 0x47, 0xb3, 0x30, 0x01, 0x59, 0xec, 0x7c, 0x8d, 0x7e, 0x0a, 0x0d, 0xeb, 0xc4, 0x3b, 0x06, 0x4e, 0x97, 0x41, 0x5e
-};
commit f583c34be47cd88df013cdb3b41a29fd01e67eca
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 13:56:24 2017 +0200

    generate the certificate verification data as part of the build
    
    Change-Id: I30186f76302e7666c833933b059931e8b1b7b78c

diff --git a/onlineupdate/CustomTarget_generated.mk b/onlineupdate/CustomTarget_generated.mk
new file mode 100644
index 000000000000..0c0f230387a8
--- /dev/null
+++ b/onlineupdate/CustomTarget_generated.mk
@@ -0,0 +1,30 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CustomTarget_CustomTarget,onlineupdate/generated))
+
+onlineupdate_INC := $(call gb_CustomTarget_get_workdir,onlineupdate/generated)/onlineupdate
+
+$(onlineupdate_INC)/primaryCert.h : \
+		$(SRCDIR)/onlineupdate/source/update/updater/gen_cert_header.py
+	$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),build,,1)
+	mkdir -p $(dir $@)
+	$(call gb_ExternalExecutable_get_command,python) $(SRCDIR)/onlineupdate/source/update/updater/gen_cert_header.py "primaryCertData" /lo/users/moggi/NSSDBDir/master-daily.der > $(onlineupdate_INC)/primaryCert.h #"$(UPDATE_CONFIG)"
+
+$(onlineupdate_INC)/secondaryCert.h : \
+		$(SRCDIR)/onlineupdate/source/update/updater/gen_cert_header.py
+	$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),build,,1)
+	mkdir -p $(dir $@)
+	$(call gb_ExternalExecutable_get_command,python) $(SRCDIR)/onlineupdate/source/update/updater/gen_cert_header.py "secondaryCertData" /lo/users/moggi/NSSDBDir/master-daily.der > $(onlineupdate_INC)/secondaryCert.h #"$(UPDATE_CONFIG)"
+
+$(call gb_CustomTarget_get_target,onlineupdate/generated) : \
+	$(onlineupdate_INC)/primaryCert.h \
+	$(onlineupdate_INC)/secondaryCert.h \
+
+# vim: set noet sw=4 ts=4:
diff --git a/onlineupdate/Executable_updater.mk b/onlineupdate/Executable_updater.mk
index 8d1b9be81ff2..ed20b19410d4 100644
--- a/onlineupdate/Executable_updater.mk
+++ b/onlineupdate/Executable_updater.mk
@@ -16,6 +16,8 @@ $(eval $(call gb_Executable_set_include,updater,\
 	$$(INCLUDE) \
 ))
 
+$(eval $(call gb_Executable_use_custom_headers,updater,onlineupdate/generated))
+
 $(eval $(call gb_Executable_use_static_libraries,updater,\
     libmar \
     updatehelper \
diff --git a/onlineupdate/Module_onlineupdate.mk b/onlineupdate/Module_onlineupdate.mk
index dfb8d54ef70c..8222be7a4ea6 100644
--- a/onlineupdate/Module_onlineupdate.mk
+++ b/onlineupdate/Module_onlineupdate.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_Module_add_targets,onlineupdate,\
 	Executable_mar \
 	Executable_updater \
 	Executable_mbsdiff \
+	CustomTarget_generated \
 ))
 endif
 
diff --git a/onlineupdate/source/update/updater/archivereader.cxx b/onlineupdate/source/update/updater/archivereader.cxx
index b0395d14094e..ec043680c27e 100644
--- a/onlineupdate/source/update/updater/archivereader.cxx
+++ b/onlineupdate/source/update/updater/archivereader.cxx
@@ -20,8 +20,8 @@
 #ifdef TEST_UPDATER
 #include "../xpcshellCert.h"
 #else
-#include "primaryCert.h"
-#include "secondaryCert.h"
+#include "onlineupdate/primaryCert.h"
+#include "onlineupdate/secondaryCert.h"
 #endif
 #endif
 
diff --git a/onlineupdate/source/update/updater/gen_cert_header.py b/onlineupdate/source/update/updater/gen_cert_header.py
index 5fff9be79084..5b70758db3f2 100755
--- a/onlineupdate/source/update/updater/gen_cert_header.py
+++ b/onlineupdate/source/update/updater/gen_cert_header.py
@@ -1,27 +1,22 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import sys
 import binascii
 
-def file_byte_generator(filename, block_size = 512):
-  with open(filename, "rb") as f:
-    while True:
-      block = f.read(block_size)
-      if block:
-        for byte in block:
-          yield byte
-      else:
-        break
+def file_byte_generator(filename):
+    with open(filename, "rb") as f:
+        block = f.read()
+        return block
 
 def create_header(array_name, in_filename):
-  hexified = ["0x" + binascii.hexlify(byte) for byte in file_byte_generator(in_filename)]
-  print("const uint8_t " + array_name + "[] = {")
-  print(", ".join(hexified))
-  print("};")
-  return 0
+    hexified = ["0x" + binascii.hexlify(bytes([inp])).decode('ascii') for inp in file_byte_generator(in_filename)]
+    print("const uint8_t " + array_name + "[] = {")
+    print(", ".join(hexified))
+    print("};")
+    return 0
 
 if __name__ == '__main__':
-  if len(sys.argv) < 3:
-    print('ERROR: usage: gen_cert_header.py array_name in_filename')
-    sys.exit(1);
-  sys.exit(create_header(sys.argv[1], sys.argv[2]))
+    if len(sys.argv) < 3:
+        print('ERROR: usage: gen_cert_header.py array_name in_filename')
+        sys.exit(1);
+    sys.exit(create_header(sys.argv[1], sys.argv[2]))
commit 410f06f9d1add43e5e7f7f43c3cf73fd7940baee
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 09:52:53 2017 +0200

    remove double '/' in update download URL
    
    Change-Id: I4dc4c1407d82b10adf8ad677ce192d1bd30aeaa2

diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index b57b3d1879ba..5d60916ec700 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -607,7 +607,7 @@ void update_checker()
     OUString aChannel = officecfg::Office::Update::Update::UpdateChannel::get();
 
     OUString aDownloadCheckURL = aDownloadCheckBaseURL + "update/check/1/" + aProductName +
-        "/" + aBuildID + "/" + aBuildTarget + "/" + "/" + aChannel;
+        "/" + aBuildID + "/" + aBuildTarget + "/" + aChannel;
     OString aURL = OUStringToOString(aDownloadCheckURL, RTL_TEXTENCODING_UTF8);
     Updater::log("Update check: " + aURL);
 
commit 7fd9b949192f6f8cdee941c1aa734d4a2ac084f1
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 06:55:02 2017 +0200

    second part for user profile in instdir
    
    This handles the replacement request part.
    
    The algorithm moves the user profile out of the backup back into the
    user profile.
    
    Change-Id: Ide45009d7a42b01ee645418b1a0c30b211842510

diff --git a/onlineupdate/source/update/common/updatedefines.h b/onlineupdate/source/update/common/updatedefines.h
index acca6887f422..748f9e098dd6 100644
--- a/onlineupdate/source/update/common/updatedefines.h
+++ b/onlineupdate/source/update/common/updatedefines.h
@@ -70,6 +70,7 @@ static inline int mywcsprintf(WCHAR* dest, size_t count, const WCHAR* fmt, ...)
 # define NS_tstat_t _stat
 # define NS_tstrcat wcscat
 # define NS_tstrcmp wcscmp
+# define NS_tstrncmp wcsncmp
 # define NS_tstricmp wcsicmp
 # define NS_tstrcpy wcscpy
 # define NS_tstrncpy wcsncpy
@@ -115,6 +116,7 @@ static inline int mywcsprintf(WCHAR* dest, size_t count, const WCHAR* fmt, ...)
 # define NS_tlstat lstat
 # define NS_tstrcat strcat
 # define NS_tstrcmp strcmp
+# define NS_tstrncmp strncmp
 # define NS_tstricmp strcasecmp
 # define NS_tstrcpy strcpy
 # define NS_tstrncpy strncpy
diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx
index e6eb3855286c..e81fd89e840b 100644
--- a/onlineupdate/source/update/updater/updater.cxx
+++ b/onlineupdate/source/update/updater/updater.cxx
@@ -332,6 +332,32 @@ get_full_path(const NS_tchar *relpath)
     return s;
 }
 
+namespace {
+
+bool is_userprofile_in_instdir()
+{
+    // the algorithm is:
+    // 1.) if userprofile path length is smaller than installation dir,
+    //      the profile is surely not in instdir
+    // 2.) else comparing the two paths looking only at the installation dir
+    //      characters should yield an equal string
+    NS_tchar userprofile[MAXPATHLEN];
+    NS_tstrcpy(userprofile, gPatchDirPath);
+    NS_tchar *slash = (NS_tchar *) NS_tstrrchr(userprofile, NS_T('/'));
+    if (slash)
+        *slash = NS_T('\0');
+
+    size_t userprofile_len = NS_tstrlen(userprofile);
+    size_t installdir_len = NS_tstrlen(gInstallDirPath);
+
+    if (userprofile_len < installdir_len)
+        return false;
+
+    return NS_tstrncmp(userprofile, gInstallDirPath, installdir_len) == 0;
+}
+
+}
+
 /**
  * Converts a full update path into a relative path; reverses get_full_path.
  *
@@ -2406,6 +2432,31 @@ ProcessReplaceRequest()
         return rv;
     }
 
+    if (is_userprofile_in_instdir())
+    {
+        // 1.) calculate path of the user profile in the backup directory
+        // 2.) move the user profile from the backup to the install directory
+        NS_tchar backup_user_profile[MAXPATHLEN];
+        NS_tchar userprofile[MAXPATHLEN];
+
+        NS_tstrcpy(userprofile, gPatchDirPath);
+        NS_tchar *slash = (NS_tchar *) NS_tstrrchr(userprofile, NS_T('/'));
+        if (slash)
+            *slash = NS_T('\0');
+        NS_tstrcpy(backup_user_profile, tmpDir);
+        size_t installdir_len = NS_tstrlen(destDir);
+
+        NS_tstrcat(backup_user_profile, userprofile + installdir_len);
+        if (slash)
+            *slash = NS_T('/');
+        LOG(("copy user profile back from " LOG_S " to " LOG_S, backup_user_profile, userprofile));
+        int rv2 = rename_file(backup_user_profile, userprofile);
+        if (rv2)
+        {
+            LOG(("failed to copy user profile back"));
+        }
+    }
+
 #if !defined(_WIN32) && !defined(MACOSX)
     // Platforms that have their updates directory in the installation directory
     // need to have the last-update.log and backup-update.log files moved from the
commit 6461edc7cc7318d94bf68c49d97311c96793cf8c
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 04:46:30 2017 +0200

    first step into supporting user profile in installation dir
    
    Change-Id: I2485ad2b69ed28b7f964540ac3eecd22099b4f7c

diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx
index 1e36b4d300f8..e6eb3855286c 100644
--- a/onlineupdate/source/update/updater/updater.cxx
+++ b/onlineupdate/source/update/updater/updater.cxx
@@ -735,6 +735,11 @@ struct copy_recursive_skiplist
         NS_tsnprintf(paths[index], MAXPATHLEN, NS_T("%s/%s"), path, suffix);
     }
 
+    void append(unsigned index, const NS_tchar* path)
+    {
+        NS_tstrcpy(paths[index], path);
+    }
+
     bool find(const NS_tchar *path)
     {
         for (int i = 0; i < static_cast<int>(N); ++i)
@@ -2262,18 +2267,28 @@ CopyInstallDirToDestDir()
 {
     // These files should not be copied over to the updated app
 #ifdef _WIN32
-#define SKIPLIST_COUNT 3
+#define SKIPLIST_COUNT 4
 #elif defined(MACOSX)
-#define SKIPLIST_COUNT 0
+#define SKIPLIST_COUNT 1
 #else
-#define SKIPLIST_COUNT 2
+#define SKIPLIST_COUNT 3
 #endif
     copy_recursive_skiplist<SKIPLIST_COUNT> skiplist;
+
+    std::unique_ptr<NS_tchar> pUserProfile(new NS_tchar[MAXPATHLEN]);
+    NS_tstrcpy(pUserProfile.get(), gPatchDirPath);
+    NS_tchar *slash = (NS_tchar *) NS_tstrrchr(pUserProfile.get(), NS_T('/'));
+    if (slash)
+        *slash = NS_T('\0');
+
+    LOG(("ignore user profile directory during copy: " LOG_S, pUserProfile.get()));
+
+    skiplist.append(0, pUserProfile.get());
 #ifndef MACOSX
-    skiplist.append(0, gInstallDirPath, NS_T("updated"));
-    skiplist.append(1, gInstallDirPath, NS_T("updates/0"));
+    skiplist.append(1, gInstallDirPath, NS_T("updated"));
+    skiplist.append(2, gInstallDirPath, NS_T("updates/0"));
 #ifdef _WIN32
-    skiplist.append(2, gInstallDirPath, NS_T("updated.update_in_progress.lock"));
+    skiplist.append(4, gInstallDirPath, NS_T("updated.update_in_progress.lock"));
 #endif
 #endif
 
@@ -2289,6 +2304,8 @@ CopyInstallDirToDestDir()
 static int
 ProcessReplaceRequest()
 {
+    // TODO: moggi: handle the user profile in the installation dir also
+    // during the replacement request
     // The replacement algorithm is like this:
     // 1. Move destDir to tmpDir.  In case of failure, abort.
     // 2. Move newDir to destDir.  In case of failure, revert step 1 and abort.
commit a31b5bb137ca143e91f7cfeecb19ea5a14ea5e88
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 03:07:02 2017 +0200

    extract string typedefs to a shared file
    
    Change-Id: I6e5d7c828f56b6a3f562ed8a9dd5f63a9d603ce0

diff --git a/onlineupdate/inc/types.hxx b/onlineupdate/inc/types.hxx
new file mode 100644
index 000000000000..3e83a19c7d78
--- /dev/null
+++ b/onlineupdate/inc/types.hxx
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ONLINEUPDATE_TYPES_HXX
+#define INCLUDED_ONLINEUPDATE_TYPES_HXX
+
+#include <string>
+
+#if defined(_WIN32)
+typedef std::wstring tstring;
+typedef WCHAR NS_tchar;
+#else
+typedef std::string tstring;
+typedef char NS_tchar;
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/onlineupdate/source/update/common/readstrings.h b/onlineupdate/source/update/common/readstrings.h
index bc837ef326b5..747081394c10 100644
--- a/onlineupdate/source/update/common/readstrings.h
+++ b/onlineupdate/source/update/common/readstrings.h
@@ -11,14 +11,9 @@
 
 #ifdef _WIN32
 # include <windows.h>
-typedef WCHAR NS_tchar;
-#else
-typedef char NS_tchar;
 #endif
 
-#ifndef NULL
-#define NULL 0
-#endif
+#include "types.hxx"
 
 struct StringTable
 {
diff --git a/onlineupdate/source/update/updater/archivereader.h b/onlineupdate/source/update/updater/archivereader.h
index 9b7885dc0103..090b787f9cf5 100644
--- a/onlineupdate/source/update/updater/archivereader.h
+++ b/onlineupdate/source/update/updater/archivereader.h
@@ -9,12 +9,7 @@
 
 #include <stdio.h>
 #include <onlineupdate/mar.h>
-
-#ifdef _WIN32
-typedef WCHAR NS_tchar;
-#else
-typedef char NS_tchar;
-#endif
+#include "types.hxx"
 
 // This class provides an API to extract files from an update archive.
 class ArchiveReader
diff --git a/onlineupdate/source/update/updater/progressui.h b/onlineupdate/source/update/updater/progressui.h
index 455ae125180a..cb1468d3949c 100644
--- a/onlineupdate/source/update/updater/progressui.h
+++ b/onlineupdate/source/update/updater/progressui.h
@@ -8,12 +8,11 @@
 #define PROGRESSUI_H__
 
 #include "updatedefines.h"
+#include "types.hxx"
 
 #if defined(_WIN32)
-typedef WCHAR NS_tchar;
 #define NS_main wmain
 #else
-typedef char NS_tchar;
 #define NS_main main
 #endif
 
commit 2a241aa2601b2286974b98bb90d648256a6dc2ae
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed May 3 22:51:57 2017 +0200

    add TODO
    
    Change-Id: I2d913a878aba91fea41a010237dd685845b5b648

diff --git a/onlineupdate/source/service/serviceinstall.cxx b/onlineupdate/source/service/serviceinstall.cxx
index a225e9445544..0bbc875086be 100644
--- a/onlineupdate/source/service/serviceinstall.cxx
+++ b/onlineupdate/source/service/serviceinstall.cxx
@@ -75,6 +75,7 @@ ReadMaintenanceServiceStrings(LPCWSTR path,
 {
     // Read in the maintenance service description string if specified.
     const unsigned int kNumStrings = 1;
+    // TODO: moggi: needs adaption for LibreOffice
     const char *kServiceKeys = "MozillaMaintenanceDescription\0";
     char serviceStrings[kNumStrings][MAX_TEXT_LEN];
     int result = ReadStrings(path, kServiceKeys,
commit a28749392d2ad5b29af99f5db4a37be64fdba09c
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed May 3 22:50:54 2017 +0200

    remove unused hard link support
    
    Change-Id: I7f40598df74c8731b13c37b8adaa636086d204b4

diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx
index 3c5baca1e3ac..1e36b4d300f8 100644
--- a/onlineupdate/source/update/updater/updater.cxx
+++ b/onlineupdate/source/update/updater/updater.cxx
@@ -112,8 +112,6 @@ struct UpdateServerThreadArgs
 #define USE_EXECV
 #endif
 
-# define MAYBE_USE_HARD_LINKS 0
-
 #if defined(VERIFY_MAR_SIGNATURE) && !defined(_WIN32) && !defined(MACOSX)
 #include <nss.h>
 #include <nspr.h>
@@ -639,26 +637,6 @@ static int ensure_copy_symlink(const NS_tchar *path, const NS_tchar *dest)
 }
 #endif
 
-#if MAYBE_USE_HARD_LINKS
-/*
- * Creates a hardlink (destFilename) which points to the existing file
- * (srcFilename).
- *
- * @return 0 if successful, an error otherwise
- */
-
-static int
-create_hard_link(const NS_tchar *srcFilename, const NS_tchar *destFilename)
-{
-    if (link(srcFilename, destFilename) < 0)
-    {
-        LOG(("link(%s, %s) failed errno = %d", srcFilename, destFilename, errno));
-        return WRITE_ERROR;
-    }
-    return OK;
-}
-#endif
-
 // Copy the file named path onto a new file named dest.
 static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
 {
@@ -689,18 +667,6 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
     }
 #endif
 
-#if MAYBE_USE_HARD_LINKS
-    if (sUseHardLinks)
-    {
-        if (!create_hard_link(path, dest))
-        {
-            return OK;
-        }
-        // Since we failed to create the hard link, fall through and copy the file.
-        sUseHardLinks = false;
-    }
-#endif
-
     AutoFile infile(ensure_open(path, NS_T("rb"), ss.st_mode));
     if (!infile)
     {
commit cd5b6299298acf110f56b6abefc4254677c5112e
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed May 3 00:36:06 2017 +0200

    without the wb+ reading the patch file will fail
    
    Change-Id: I61be299647d41bb464bea039630ddd4ff545f412

diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx
index 57ac77507a8b..3c5baca1e3ac 100644
--- a/onlineupdate/source/update/updater/updater.cxx
+++ b/onlineupdate/source/update/updater/updater.cxx
@@ -1610,7 +1610,7 @@ PatchFile::Prepare()
 
     NS_tremove(spath);
 
-    mPatchStream = NS_tfopen(spath, NS_T("wb"));
+    mPatchStream = NS_tfopen(spath, NS_T("wb+"));
     if (!mPatchStream)
         return WRITE_ERROR;
 
commit 15fe23478500ffd17ef420a17fa4dd8ce0b14ebd
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri Apr 28 01:28:28 2017 +0200

    log all the updater actions
    
    Change-Id: Ia7b08c4e93d5b3b65b0f44af9c92f5e6f6fafd96

diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index cad36200daaa..b57b3d1879ba 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -233,6 +233,7 @@ void update()
 
 void CreateValidUpdateDir(const update_info& update_info)
 {
+    Updater::log(OString("Create Update Dir"));
     OUString aInstallDir("$BRAND_BASE_DIR");
     rtl::Bootstrap::expandMacros(aInstallDir);
     OUString aInstallPath = getPathFromURL(aInstallDir);
@@ -255,6 +256,7 @@ void CreateValidUpdateDir(const update_info& update_info)
     {
         // TODO: remove the update directory
         SAL_WARN("desktop.updater", "failed to update");
+        Updater::log(OUString("failed to create update dir"));
     }
     else
     {
@@ -471,6 +473,7 @@ size_t WriteCallbackFile(void *ptr, size_t size,
 
 std::string download_content(const OString& rURL, bool bFile, OUString& rHash)
 {
+    Updater::log("Download: " + rURL);
     CURL* curl = curl_easy_init();
 
     if (!curl)
@@ -606,7 +609,7 @@ void update_checker()
     OUString aDownloadCheckURL = aDownloadCheckBaseURL + "update/check/1/" + aProductName +
         "/" + aBuildID + "/" + aBuildTarget + "/" + "/" + aChannel;
     OString aURL = OUStringToOString(aDownloadCheckURL, RTL_TEXTENCODING_UTF8);
-
+    Updater::log("Update check: " + aURL);
 
     try
     {
@@ -620,10 +623,16 @@ void update_checker()
                 // No update currently available
                 // add entry to updating.log with the message
                 SAL_WARN("desktop.updater", "Message received from the updater: " << aUpdateInfo.aMessage);
+                Updater::log("Server response: " + aUpdateInfo.aMessage);
             }
             else
             {
                 download_file(aUpdateInfo.aUpdateFile.aURL, aUpdateInfo.aUpdateFile.nSize, aUpdateInfo.aUpdateFile.aHash, "update.mar");
+                for (auto& lang_update : aUpdateInfo.aLanguageFiles)
+                {
+                    OUString aFileName = "update_" + lang_update.aLangCode + ".mar";
+                    download_file(lang_update.aUpdateFile.aURL, lang_update.aUpdateFile.nSize, lang_update.aUpdateFile.aHash, aFileName);
+                }
                 CreateValidUpdateDir(aUpdateInfo);
             }
         }
@@ -631,22 +640,27 @@ void update_checker()
     catch (const invalid_update_info&)
     {
         SAL_WARN("desktop.updater", "invalid update information");
+        Updater::log(OString("warning: invalid update info"));
     }
     catch (const error_updater&)
     {
         SAL_WARN("desktop.updater", "error during the update check");
+        Updater::log(OString("warning: error by the updater"));
     }
     catch (const invalid_size& e)
     {
         SAL_WARN("desktop.updater", e.what());
+        Updater::log(OString("warning: invalid size"));
     }
     catch (const invalid_hash& e)
     {
         SAL_WARN("desktop.updater", e.what());
+        Updater::log(OString("warning: invalid hash"));
     }
     catch (...)
     {
         SAL_WARN("desktop.updater", "unknown error during the update check");
+        Updater::log(OString("warning: unknown exception"));
     }
 }
 
@@ -658,6 +672,14 @@ OUString Updater::getUpdateInfoURL()
     return aUpdateInfoURL;
 }
 
+OUString Updater::getUpdateInfoLog()
+{
+    OUString aUpdateInfoURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/updating.log");
+    rtl::Bootstrap::expandMacros(aUpdateInfoURL);
+
+    return aUpdateInfoURL;
+}
+
 OUString Updater::getPatchDirURL()
 {
     OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/");
@@ -682,4 +704,20 @@ OUString Updater::getExecutableDirURL()
     return aExeDir;
 }
 
+void Updater::log(const OUString& rMessage)
+{
+    OUString aUpdateLog = getUpdateInfoLog();
+    SvFileStream aLog(aUpdateLog, StreamMode::STD_READWRITE);
+    aLog.Seek(aLog.Tell() + aLog.remainingSize()); // make sure we are at the end
+    aLog.WriteLine(OUStringToOString(rMessage, RTL_TEXTENCODING_UTF8));
+}
+
+void Updater::log(const OString& rMessage)
+{
+    OUString aUpdateLog = getUpdateInfoLog();
+    SvFileStream aLog(aUpdateLog, StreamMode::STD_READWRITE);
+    aLog.Seek(aLog.Tell() + aLog.remainingSize()); // make sure we are at the end
+    aLog.WriteLine(rMessage);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/app/updater.hxx b/desktop/source/app/updater.hxx
index b36c1f91b306..f3f28bc638ec 100644
--- a/desktop/source/app/updater.hxx
+++ b/desktop/source/app/updater.hxx
@@ -23,10 +23,13 @@ private:
 public:
 
     static OUString getUpdateInfoURL();
+    static OUString getUpdateInfoLog();
     static OUString getPatchDirURL();
     static OUString getUpdateDirURL();
     static OUString getExecutableDirURL();
 
+    static void log(const OUString& rMessage);
+    static void log(const OString& rMessage);
 };
 
 #endif
commit 357f5e0525b555f5bcfedcef0d775a4dda6515fa
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu Apr 27 03:02:22 2017 +0200

    fix errors in upload scripts
    
    Change-Id: I0ee9fbef7b80e5d37800b4fb9daff7e8ba46d65d

diff --git a/bin/update/create_build_config.py b/bin/update/create_build_config.py
index 163e94a4426f..8d6bf5206ce8 100755
--- a/bin/update/create_build_config.py
+++ b/bin/update/create_build_config.py
@@ -17,7 +17,7 @@ def update_all_url_entries(data, **kwargs):
         for partial in data['partials']:
             partial['file']['url'] = replace_variables_in_string(partial['file']['url'], **kwargs)
 
-            for lang, lang_file in partial['languages'].iter():
+            for lang, lang_file in partial['languages'].items():
                 lang_file['url'] = replace_variables_in_string(lang_file['url'], **kwargs)
 
 def main(argv):
diff --git a/bin/update/create_full_mar.py b/bin/update/create_full_mar.py
index a9d7aa2b9fe5..38919542d6a4 100755
--- a/bin/update/create_full_mar.py
+++ b/bin/update/create_full_mar.py
@@ -12,8 +12,6 @@ from path import UpdaterPath
 
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
 
-def ensure_dir_exist()
-
 def main():
     if len(sys.argv) < 5:
         print("Usage: create_full_mar_for_languages.py $PRODUCTNAME $WORKDIR $FILENAMEPREFIX $UPDATE_CONFIG")
commit a85eed49551cc867ff86d89efd81cbee0ea19191
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu Apr 27 01:30:19 2017 +0200

    integrate the partial update info into the uploaded info
    
    Change-Id: I1b6fc7970d3010c63ae910d55103efb504e15b53

diff --git a/Makefile.gbuild b/Makefile.gbuild
index 44637577da52..61ad648aad79 100644
--- a/Makefile.gbuild
+++ b/Makefile.gbuild
@@ -35,12 +35,12 @@ create-update-info:
 	mkdir -p $(MAR_DIR)/language
 	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_full_mar.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)"
 	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_full_mar_for_languages.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)"
-	$(SRCDIR)/bin/update/create_build_config.py "$(PRODUCTNAME)" "$(VERSION)" "$(BUILDID)" "$(PLATFORM)" "$(UPDATE_DIR)" "$(UPDATE_CONFIG)"
 
 upload-update-info:
 	$(eval BUILDID := $(shell git -C $(SRCDIR) log -1 --format=%H))
 	$(eval PLATFORM := $(RTL_OS)_$(RTL_ARCH))
 	$(eval UPDATE_DIR := $(WORKDIR)/update-info)
+	$(SRCDIR)/bin/update/create_build_config.py "$(PRODUCTNAME)" "$(VERSION)" "$(BUILDID)" "$(PLATFORM)" "$(UPDATE_DIR)" "$(UPDATE_CONFIG)"
 	$(SRCDIR)/bin/update/upload_builds.py "$(PRODUCTNAME)" "$(BUILDID)" "$(PLATFORM)" "$(UPDATE_DIR)" "$(UPDATE_CONFIG)"
 	$(SRCDIR)/bin/update/upload_build_config.py "$(UPDATE_DIR)" "$(UPDATE_CONFIG)"
 
diff --git a/bin/update/create_build_config.py b/bin/update/create_build_config.py
index 8d0cf0e07cbe..163e94a4426f 100755
--- a/bin/update/create_build_config.py
+++ b/bin/update/create_build_config.py
@@ -13,6 +13,13 @@ def update_all_url_entries(data, **kwargs):
     for language in data['languages']:
         language['complete']['url'] = replace_variables_in_string(language['complete']['url'], **kwargs)
 
+    if 'partials' in data:
+        for partial in data['partials']:
+            partial['file']['url'] = replace_variables_in_string(partial['file']['url'], **kwargs)
+
+            for lang, lang_file in partial['languages'].iter():
+                lang_file['url'] = replace_variables_in_string(lang_file['url'], **kwargs)
+
 def main(argv):
     if len(argv) < 7:
         print("Usage: create_build_config.py $PRODUCTNAME $VERSION $BUILDID $PLATFORM $TARGETDIR $UPDATE_CONFIG")
@@ -26,7 +33,7 @@ def main(argv):
             'platform' : argv[4]
             }
 
-    extra_data_files = ['complete_info.json', 'complete_lang_info.json']
+    extra_data_files = ['complete_info.json', 'complete_lang_info.json', 'partial_update_info.json']
 
     for extra_file in extra_data_files:
         extra_file_path = os.path.join(argv[5], extra_file)
commit 0c288f5301e2f541b5f771b15f7b99accc4e471e
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu Apr 27 00:07:43 2017 +0200

    use file instead of complete for the key of the partial update info
    
    Change-Id: Ifbb482a4fd9c1c92e9cdd7769d4b16160de14a86

diff --git a/bin/update/create_partial_update.py b/bin/update/create_partial_update.py
index 419a8f65226b..23d4f6fe6a90 100755
--- a/bin/update/create_partial_update.py
+++ b/bin/update/create_partial_update.py
@@ -129,7 +129,7 @@ def main():
         subprocess.call([os.path.join(current_dir_path, 'make_incremental_update.sh'), mar_file, update["complete"], current_build_path])
         sign_mar_file(update_dir, config, mar_file, mar_name_prefix)
 
-        partial_info = {"complete":get_file_info(mar_file, config.base_url), "from": build, "to": build_id, "languages": {}}
+        partial_info = {"file":get_file_info(mar_file, config.base_url), "from": build, "to": build_id, "languages": {}}
         for lang, lang_info in update["languages"].items():
             lang_name = generate_lang_file_name(build_id, build, mar_name_prefix, lang)
 
commit 2ffd3ccd83ea267439fe0be696ca61720a7cbb3b
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 23:58:57 2017 +0200

    add missing file
    
    Change-Id: I7cd9d541b90f4f6b38aa5e36e295e7677bb22f58

diff --git a/bin/update/path.py b/bin/update/path.py
new file mode 100644
index 000000000000..1bc14d70d940
--- /dev/null
+++ b/bin/update/path.py
@@ -0,0 +1,52 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import os
+import errno
+
+def mkdir_p(path):
+    try:
+        os.makedirs(path)
+    except OSError as exc:  # Python >2.5
+        if exc.errno == errno.EEXIST and os.path.isdir(path):
+            pass
+        else:
+            raise
+
+class UpdaterPath(object):
+
+    def __init__(self, workdir):
+        self._workdir = workdir
+
+    def get_workdir(self):
+        return self._workdir
+
+    def get_update_dir(self):
+        return os.path.join(self._workdir, "update-info")
+
+    def get_current_build_dir(self):
+        return os.path.join(self._workdir, "mar", "current-build")
+
+    def get_mar_dir(self):
+        return os.path.join(self._workdir, "mar")
+
+    def get_previous_build_dir(self):
+        return os.path.join(self._workdir, "mar", "previous-build")
+
+    def get_language_dir(self):
+        return os.path.join(self.get_mar_dir(), "language")
+    
+    def ensure_dir_exist(self):
+        mkdir_p(self.get_update_dir())
+        mkdir_p(self.get_current_build_dir())
+        mkdir_p(self.get_mar_dir())
+        mkdir_p(self.get_previous_build_dir())
+        mkdir_p(self.get_language_dir())
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
commit 7b45ae4d2f5a6d176f6225029cc67f0749a9de74
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 23:58:05 2017 +0200

    use the shared signing code
    
    Change-Id: Ica0fad83820569623f3cc2f0217ac9cd8ee19257

diff --git a/bin/update/create_full_mar_for_languages.py b/bin/update/create_full_mar_for_languages.py
index 98e1b1c539e7..039521dd10af 100755
--- a/bin/update/create_full_mar_for_languages.py
+++ b/bin/update/create_full_mar_for_languages.py
@@ -9,6 +9,7 @@ from tools import uncompress_file_to_dir, get_file_info
 
 from config import parse_config
 from path import UpdaterPath
+from signing import sign_mar_file
 
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
 
@@ -38,8 +39,6 @@ def main():
 
     config = parse_config(update_config)
 
-    mar_executable = os.environ.get('MAR', 'mar')
-
     language_pack_dir = os.path.join(workdir, "installation", product_name + "_languagepack", "archive", "install")
     language_packs = os.listdir(language_pack_dir)
     lang_infos = []
@@ -56,9 +55,7 @@ def main():
 
         subprocess.call([os.path.join(current_dir_path, 'make_full_update.sh'), mar_file_name, directory])
 
-        signed_mar_file = make_complete_mar_name(target_dir, filename_prefix + '_signed', language)
-        subprocess.call([mar_executable, '-C', target_dir, '-d', config.certificate_path, '-n', config.certificate_name, '-s', mar_file_name, signed_mar_file])
-        os.rename(signed_mar_file, mar_file_name)
+        sign_mar_file(target_dir, config, mar_file_name, filename_prefix)
 
         lang_infos.append(create_lang_infos(mar_file_name, language, config.base_url))
 
commit 558fee49c9bacdad7313b3392b9e755fc453813a
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 23:49:31 2017 +0200

    simplify path handling in the updater scripts
    
    Change-Id: Idcf7f9cedc2368f6a4e4e10c2852cc9b1125b712

diff --git a/Makefile.gbuild b/Makefile.gbuild
index ed08c6217d13..44637577da52 100644
--- a/Makefile.gbuild
+++ b/Makefile.gbuild
@@ -32,12 +32,10 @@ create-update-info:
 	$(eval MAR_DIR := $(WORKDIR)/mar)
 	rm -rf $(MAR_DIR) || true
 	rm -rf $(UPDATE_DIR) || true
-	mkdir -p $(UPDATE_DIR)
-	mkdir -p $(MAR_DIR)/current-build
 	mkdir -p $(MAR_DIR)/language
-	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_full_mar.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(UPDATE_DIR)" "$(MAR_DIR)/current-build/" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)"
-	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_full_mar_for_languages.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(UPDATE_DIR)" "$(MAR_DIR)/language" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)"
-	$(SRCDIR)/bin/update/create_build_config.py "$(PRODUCTNAME)" "$(VERSION)" "$(BUILDID)" "$(PLATFORM)" "$(UPDATE_DIR)" "$(UPDATE_CONFIG)" "$(UPDATE_CONFIG)"
+	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_full_mar.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)"
+	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_full_mar_for_languages.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)"
+	$(SRCDIR)/bin/update/create_build_config.py "$(PRODUCTNAME)" "$(VERSION)" "$(BUILDID)" "$(PLATFORM)" "$(UPDATE_DIR)" "$(UPDATE_CONFIG)"
 
 upload-update-info:
 	$(eval BUILDID := $(shell git -C $(SRCDIR) log -1 --format=%H))
@@ -51,11 +49,6 @@ create-partial-info:
 	$(eval VERSION := $(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)$(LIBO_VERSION_SUFFIX)$(LIBO_VERSION_SUFFIX_SUFFIX))
 	$(eval PLATFORM := $(RTL_OS)_$(RTL_ARCH))
 	$(eval MAR_NAME_PREFIX := $(PRODUCTNAME)_$(VERSION)_$(PLATFORM)_$(BUILDID))
-	$(eval UPDATE_DIR := $(WORKDIR)/update-info)
-	$(eval MAR_DIR := $(WORKDIR)/mar)
-	$(eval CURRENT_BUILD := $(WORKDIR)/mar/current-build/)
-	mkdir -p $(UPDATE_DIR)
-	mkdir -p $(UPDATE_DIR)/previous-builds
-	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_partial_update.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(UPDATE_DIR)" "$(MAR_DIR)/previous-builds/" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)" "$(PLATFORM)" "$(CURRENT_BUILD)" "$(BUILDID)" "$(MAR_DIR)"
+	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_partial_update.py "$(WORKDIR)" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)" "$(PLATFORM)" "$(BUILDID)"
 
 # vim: set noet sw=4 ts=4:
diff --git a/bin/update/create_full_mar.py b/bin/update/create_full_mar.py
index 649eafe2bfa6..a9d7aa2b9fe5 100755
--- a/bin/update/create_full_mar.py
+++ b/bin/update/create_full_mar.py
@@ -8,19 +8,19 @@ import json
 from tools import uncompress_file_to_dir, get_file_info, make_complete_mar_name
 from config import parse_config
 from signing import sign_mar_file
+from path import UpdaterPath
 
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
 
+def ensure_dir_exist()
+
 def main():
-    print(sys.argv)
-    if len(sys.argv) < 7:
-        print("Usage: create_full_mar_for_languages.py $PRODUCTNAME $WORKDIR $TARGETDIR $TEMPDIR $FILENAMEPREFIX $UPDATE_CONFIG")
+    if len(sys.argv) < 5:
+        print("Usage: create_full_mar_for_languages.py $PRODUCTNAME $WORKDIR $FILENAMEPREFIX $UPDATE_CONFIG")
         sys.exit(1)
 
-    update_config = sys.argv[6]
-    filename_prefix = sys.argv[5]
-    temp_dir = sys.argv[4]
-    target_dir = sys.argv[3]
+    update_config = sys.argv[4]
+    filename_prefix = sys.argv[3]
     workdir = sys.argv[2]
     product_name = sys.argv[1]
 
@@ -28,6 +28,12 @@ def main():
         print("missing update config")
         sys.exit(1)
 
+    update_path = UpdaterPath(workdir)
+    update_path.ensure_dir_exist()
+
+    target_dir = update_path.get_update_dir()
+    temp_dir = update_path.get_current_build_dir()
+
     config = parse_config(update_config)
 
     tar_dir = os.path.join(workdir, "installation", product_name, "archive", "install", "en-US")
diff --git a/bin/update/create_full_mar_for_languages.py b/bin/update/create_full_mar_for_languages.py
index 7daf5fe6034e..98e1b1c539e7 100755
--- a/bin/update/create_full_mar_for_languages.py
+++ b/bin/update/create_full_mar_for_languages.py
@@ -8,6 +8,7 @@ import json
 from tools import uncompress_file_to_dir, get_file_info
 
 from config import parse_config
+from path import UpdaterPath
 
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
 
@@ -22,18 +23,19 @@ def create_lang_infos(mar_file_name, language, url):
     return data
 
 def main():
-    print(sys.argv)
-    if len(sys.argv) < 7:
+    if len(sys.argv) < 5:
         print("Usage: create_full_mar_for_languages.py $PRODUCTNAME $WORKDIR $TARGETDIR $TEMPDIR $FILENAMEPREFIX $UPDATE_CONFIG")
         sys.exit(1)
 
-    update_config = sys.argv[6]
-    filename_prefix = sys.argv[5]
-    temp_dir = sys.argv[4]
-    target_dir = sys.argv[3]
+    update_config = sys.argv[4]
+    filename_prefix = sys.argv[3]
     workdir = sys.argv[2]
     product_name = sys.argv[1]
 
+    updater_path = UpdaterPath(workdir)
+    target_dir = updater_path.get_update_dir()
+    temp_dir = updater_path.get_language_dir()
+
     config = parse_config(update_config)
 
     mar_executable = os.environ.get('MAR', 'mar')
diff --git a/bin/update/create_partial_update.py b/bin/update/create_partial_update.py
index ca194325d20d..419a8f65226b 100755
--- a/bin/update/create_partial_update.py
+++ b/bin/update/create_partial_update.py
@@ -10,12 +10,19 @@ import json
 
 from config import parse_config
 from uncompress_mar import extract_mar
-from tools import get_file_info
+from tools import get_file_info, get_hash
 from signing import sign_mar_file
 
+from path import UpdaterPath, mkdir_p
+
 BUF_SIZE = 1024
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
 
+def InvalidFileException(Exception):
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(self, *args, **kwargs)
+
 def download_file(filepath, url, hash_string):
     with open(filepath, "wb") as f:
         response = requests.get(url, stream=True)
@@ -26,26 +33,10 @@ def download_file(filepath, url, hash_string):
         for block in response.iter_content(1024):
             f.write(block)
 
-    with open(filepath, "rb") as f:
-        sha512 = hashlib.sha512()
-        while True:
-            data = f.read(BUF_SIZE)
-            if not data:
-                break
-            sha512.update(data)
-        file_hash = sha512.hexdigest()
+    file_hash = get_hash(filepath)
 
     if file_hash != hash_string:
-        pass
-
-def mkdir_p(path):
-    try:
-        os.makedirs(path)
-    except OSError as exc:  # Python >2.5
-        if exc.errno == errno.EEXIST and os.path.isdir(path):
-            pass
-        else:
-            raise
+        raise InvalidFileException()
 
 def handle_language(lang_entries, filedir):
     mar = os.environ.get('MAR', 'mar')
@@ -109,16 +100,20 @@ def add_single_dir(path):
     return dir_name[0]
 
 def main():
-    product_name = sys.argv[1]
-    workdir = sys.argv[2]
-    update_dir = sys.argv[3]
-    temp_dir = sys.argv[4]
-    mar_name_prefix = sys.argv[5]
-    update_config = sys.argv[6]
-    platform = sys.argv[7]
-    current_build_path = sys.argv[8]
-    build_id = sys.argv[9]
-    mar_dir = sys.argv[10]
+    workdir = sys.argv[1]
+
+    updater_path = UpdaterPath(workdir)
+    updater_path.ensure_dir_exist()
+
+    mar_name_prefix = sys.argv[2]
+    update_config = sys.argv[3]
+    platform = sys.argv[4]
+    build_id = sys.argv[5]
+
+    current_build_path = updater_path.get_current_build_dir()
+    mar_dir = updater_path.get_mar_dir()
+    temp_dir = updater_path.get_previous_build_dir()
+    update_dir = updater_path.get_update_dir()
 
     current_build_path = add_single_dir(current_build_path)
 
commit 92a3e978393c95d09d86fd668501fda5148ee48d
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 06:18:06 2017 +0200

    create valid partial language updates and write partial update info
    
    Change-Id: I4000523cfc944657714267958836dd3ce4ec3b0d

diff --git a/Makefile.gbuild b/Makefile.gbuild
index dbf0e0d40888..ed08c6217d13 100644
--- a/Makefile.gbuild
+++ b/Makefile.gbuild
@@ -56,6 +56,6 @@ create-partial-info:
 	$(eval CURRENT_BUILD := $(WORKDIR)/mar/current-build/)
 	mkdir -p $(UPDATE_DIR)
 	mkdir -p $(UPDATE_DIR)/previous-builds
-	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_partial_update.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(UPDATE_DIR)" "$(MAR_DIR)/previous-builds/" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)" "$(PLATFORM)" "$(CURRENT_BUILD)" "$(BUILDID)"
+	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_partial_update.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(UPDATE_DIR)" "$(MAR_DIR)/previous-builds/" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)" "$(PLATFORM)" "$(CURRENT_BUILD)" "$(BUILDID)" "$(MAR_DIR)"
 
 # vim: set noet sw=4 ts=4:
diff --git a/bin/update/create_partial_update.py b/bin/update/create_partial_update.py
index 0382f82e79d3..ca194325d20d 100755
--- a/bin/update/create_partial_update.py
+++ b/bin/update/create_partial_update.py
@@ -6,9 +6,12 @@ import hashlib
 import os
 import subprocess
 import errno
+import json
 
 from config import parse_config
 from uncompress_mar import extract_mar
+from tools import get_file_info
+from signing import sign_mar_file
 
 BUF_SIZE = 1024
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
@@ -94,13 +97,17 @@ def download_mar_for_update_channel_and_platform(config, platform, temp_dir):
     return downloaded_updates
 
 def generate_file_name(current_build_id, old_build_id, mar_name_prefix):
-    name = "%s_from_%s_to_%s_partial.mar" %(mar_name_prefix, current_build_id, old_build_id)
+    name = "%s_from_%s_partial.mar" %(mar_name_prefix, old_build_id)
     return name
 
 def generate_lang_file_name(current_build_id, old_build_id, mar_name_prefix, lang):
-    name = "%s_%s_from_%s_to_%s_partial.mar" %(mar_name_prefix, lang, current_build_id, old_build_id)
+    name = "%s_%s_from_%s_partial.mar" %(mar_name_prefix, lang, old_build_id)
     return name
 
+def add_single_dir(path):
+    dir_name =  [os.path.join(path, name) for name in os.listdir(path) if os.path.isdir(os.path.join(path, name))]
+    return dir_name[0]
+
 def main():
     product_name = sys.argv[1]
     workdir = sys.argv[2]
@@ -111,25 +118,42 @@ def main():
     platform = sys.argv[7]
     current_build_path = sys.argv[8]
     build_id = sys.argv[9]
-    dir_name =  [os.path.join(current_build_path, name) for name in os.listdir(current_build_path) if os.path.isdir(os.path.join(current_build_path, name))]
-    current_build_path = dir_name[0]
+    mar_dir = sys.argv[10]
+
+    current_build_path = add_single_dir(current_build_path)
 
     config = parse_config(update_config)
 
     updates = download_mar_for_update_channel_and_platform(config, platform, temp_dir)
 
-    print(updates)
+    data = {"partials": []}
+
     for build, update in updates.items():
         file_name = generate_file_name(build_id, build, mar_name_prefix)
-        mar_file = os.path.join(temp_dir, build, file_name)
-        print(mar_file)
-        print(current_build_path)
-        print(update["complete"])
-        subprocess.call([os.path.join(current_dir_path, 'make_incremental_update.sh'), mar_file, current_build_path, update["complete"]])
-        for lang in update["languages"].items():
+        mar_file = os.path.join(update_dir, file_name)
+        subprocess.call([os.path.join(current_dir_path, 'make_incremental_update.sh'), mar_file, update["complete"], current_build_path])
+        sign_mar_file(update_dir, config, mar_file, mar_name_prefix)
+
+        partial_info = {"complete":get_file_info(mar_file, config.base_url), "from": build, "to": build_id, "languages": {}}
+        for lang, lang_info in update["languages"].items():
             lang_name = generate_lang_file_name(build_id, build, mar_name_prefix, lang)
-            lang_mar_file = os.path.join(temp_dir, build, lang_name)
-            #subprocess.call([os.path.join(current_dir_path, 'make_incremental_update.sh'), mar_file, current_build_path, update["complete"]])
+
+            # write the file into the final directory
+            lang_mar_file = os.path.join(update_dir, lang_name)
+
+            # the directory of the old language file is of the form
+            # workdir/mar/language/en-US/LibreOffice_<version>_<os>_archive_langpack_<lang>/
+            language_dir = add_single_dir(os.path.join(mar_dir, "language", lang))
+            subprocess.call([os.path.join(current_dir_path, 'make_incremental_update.sh'), lang_mar_file, lang_info, language_dir])
+            sign_mar_file(update_dir, config, lang_mar_file, mar_name_prefix)
+
+            # add the partial language info
+            partial_info["languages"][lang] = get_file_info(lang_mar_file, config.base_url)
+
+        data["partials"].append(partial_info)
+
+    with open(os.path.join(update_dir, "partial_update_info.json"), "w") as f:
+        json.dump(data, f)
 
 
 if __name__ == '__main__':
commit cdf0d99605a985a2ff36138189eebd1fb228d67e
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 02:43:25 2017 +0200

    add the generation of partial update files to the makefiles
    
    It seems that the generated partial update files are now generated
    correctly. We now need to handle languages and sign the partial files as
    well as upload them.
    
    Change-Id: I69fbdad42da2c8a2d9695bc852956b82ce773f4c

diff --git a/Makefile.gbuild b/Makefile.gbuild
index 6d625bb5e5fc..dbf0e0d40888 100644
--- a/Makefile.gbuild
+++ b/Makefile.gbuild
@@ -46,4 +46,16 @@ upload-update-info:
 	$(SRCDIR)/bin/update/upload_builds.py "$(PRODUCTNAME)" "$(BUILDID)" "$(PLATFORM)" "$(UPDATE_DIR)" "$(UPDATE_CONFIG)"
 	$(SRCDIR)/bin/update/upload_build_config.py "$(UPDATE_DIR)" "$(UPDATE_CONFIG)"
 
+create-partial-info:
+	$(eval BUILDID := $(shell git -C $(SRCDIR) log -1 --format=%H))
+	$(eval VERSION := $(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)$(LIBO_VERSION_SUFFIX)$(LIBO_VERSION_SUFFIX_SUFFIX))
+	$(eval PLATFORM := $(RTL_OS)_$(RTL_ARCH))
+	$(eval MAR_NAME_PREFIX := $(PRODUCTNAME)_$(VERSION)_$(PLATFORM)_$(BUILDID))
+	$(eval UPDATE_DIR := $(WORKDIR)/update-info)
+	$(eval MAR_DIR := $(WORKDIR)/mar)
+	$(eval CURRENT_BUILD := $(WORKDIR)/mar/current-build/)
+	mkdir -p $(UPDATE_DIR)
+	mkdir -p $(UPDATE_DIR)/previous-builds
+	MAR=$(INSTDIR)/program/mar $(SRCDIR)/bin/update/create_partial_update.py "$(PRODUCTNAME)" "$(WORKDIR)" "$(UPDATE_DIR)" "$(MAR_DIR)/previous-builds/" "$(MAR_NAME_PREFIX)" "$(UPDATE_CONFIG)" "$(PLATFORM)" "$(CURRENT_BUILD)" "$(BUILDID)"
+
 # vim: set noet sw=4 ts=4:
diff --git a/Makefile.in b/Makefile.in
index e835d0d18f7f..0af8a53373a3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -426,6 +426,9 @@ create-update-info:
 upload-update-info:
 	$(MAKE) -f $(SRCDIR)/Makefile.gbuild upload-update-info
 
+create-partial-info:
+	$(MAKE) -f $(SRCDIR)/Makefile.gbuild create-partial-info
+
 dump-deps:
 	@$(SRCDIR)/bin/module-deps.pl $(MAKE) $(SRCDIR)/Makefile.gbuild
 
commit fbbfbb88f529c1066cee6cd0c37c9380960e50e2
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 02:43:02 2017 +0200

    extract the mar signing code
    
    Change-Id: I007b0b68a61242b7255a1a58a3637e3307d675aa

diff --git a/bin/update/create_full_mar.py b/bin/update/create_full_mar.py
index f4990304857e..649eafe2bfa6 100755
--- a/bin/update/create_full_mar.py
+++ b/bin/update/create_full_mar.py
@@ -7,6 +7,7 @@ import json
 
 from tools import uncompress_file_to_dir, get_file_info, make_complete_mar_name
 from config import parse_config
+from signing import sign_mar_file
 
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
 
@@ -37,10 +38,8 @@ def main():
     mar_file = make_complete_mar_name(target_dir, filename_prefix)
     subprocess.call([os.path.join(current_dir_path, 'make_full_update.sh'), mar_file, uncompress_dir])
 
-    signed_mar_file = make_mar_name(target_dir, filename_prefix + '_signed')
-    subprocess.check_call([mar_executable, '-C', target_dir, '-d', config.certificate_path, '-n', config.certificate_name, '-s', mar_file, signed_mar_file])
 
-    os.rename(signed_mar_file, mar_file)
+    sign_mar_file(target_dir, config, mar_file, filename_prefix)
 
     file_info = { 'complete' : get_file_info(mar_file, config.base_url) }
 
diff --git a/bin/update/signing.py b/bin/update/signing.py
new file mode 100644
index 000000000000..e6ac2832d844
--- /dev/null
+++ b/bin/update/signing.py
@@ -0,0 +1,11 @@
+from tools import make_complete_mar_name
+
+import os
+import subprocess
+
+def sign_mar_file(target_dir, config, mar_file, filename_prefix):
+    signed_mar_file = make_complete_mar_name(target_dir, filename_prefix + '_signed')
+    mar_executable = os.environ.get('MAR', 'mar')
+    subprocess.check_call([mar_executable, '-C', target_dir, '-d', config.certificate_path, '-n', config.certificate_name, '-s', mar_file, signed_mar_file])
+
+    os.rename(signed_mar_file, mar_file)
commit 0aacc9b533179511faaba12004937a6abd5560d4
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 02:42:15 2017 +0200

    extract mar file name generation
    
    Change-Id: If928cae4c722354d5c3e415e7cb8426a3a4412f7

diff --git a/bin/update/create_full_mar.py b/bin/update/create_full_mar.py
index ebe2a01cd2cf..f4990304857e 100755
--- a/bin/update/create_full_mar.py
+++ b/bin/update/create_full_mar.py
@@ -5,15 +5,11 @@ import os
 import subprocess
 import json
 
-from tools import uncompress_file_to_dir, get_file_info
+from tools import uncompress_file_to_dir, get_file_info, make_complete_mar_name
 from config import parse_config
 
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
 
-def make_mar_name(target_dir, filename_prefix):
-    filename = filename_prefix + "_complete.mar"
-    return os.path.join(target_dir, filename)
-
 def main():
     print(sys.argv)
     if len(sys.argv) < 7:
@@ -38,8 +34,7 @@ def main():
 
     uncompress_dir = uncompress_file_to_dir(tar_file, temp_dir)
 
-    mar_executable = os.environ.get('MAR', 'mar')
-    mar_file = make_mar_name(target_dir, filename_prefix)
+    mar_file = make_complete_mar_name(target_dir, filename_prefix)
     subprocess.call([os.path.join(current_dir_path, 'make_full_update.sh'), mar_file, uncompress_dir])
 
     signed_mar_file = make_mar_name(target_dir, filename_prefix + '_signed')
diff --git a/bin/update/tools.py b/bin/update/tools.py
index 84c7ae6fb0ab..5a3e34521b40 100644
--- a/bin/update/tools.py
+++ b/bin/update/tools.py
@@ -49,3 +49,7 @@ def replace_variables_in_string(string, **kwargs):
         new_string = new_string.replace('$(%s)'%key, val)
 
     return new_string
+
+def make_complete_mar_name(target_dir, filename_prefix):
+    filename = filename_prefix + "_complete.mar"
+    return os.path.join(target_dir, filename)
commit 039cd1217b95ee78794d24bde0315d2dc3de4475
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 02:13:45 2017 +0200

    reuse the new extract mar code for the partial update generation
    
    Change-Id: Ie8c92472631034935e73e55c934ce128c7b6ecd2

diff --git a/bin/update/create_partial_update.py b/bin/update/create_partial_update.py
index 90c2abd697e3..0382f82e79d3 100755
--- a/bin/update/create_partial_update.py
+++ b/bin/update/create_partial_update.py
@@ -8,6 +8,7 @@ import subprocess
 import errno
 
 from config import parse_config
+from uncompress_mar import extract_mar
 
 BUF_SIZE = 1024
 current_dir_path = os.path.dirname(os.path.realpath(__file__))
@@ -53,7 +54,7 @@ def handle_language(lang_entries, filedir):
         download_file(lang_file , data["url"], data["hash"])
         dir_path = os.path.join(lang_dir, "lang")
         mkdir_p(dir_path)
-        subprocess.call([mar, "-C", dir_path, "-x", lang_file])
+        extract_mar(lang_file, dir_path)
         langs[lang] = dir_path
 
     return langs
@@ -83,7 +84,7 @@ def download_mar_for_update_channel_and_platform(config, platform, temp_dir):
 
         dir_path = os.path.join(filedir, "complete")
         mkdir_p(dir_path)
-        subprocess.call([mar, "-C", dir_path, "-x", filepath])
+        extract_mar(filepath, dir_path)
 
         downloaded_updates[build] = {"complete": dir_path}
 
commit 2ce1ab2a85c0e5a3cc2c3f6e691bf6c934dd3599
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 01:55:01 2017 +0200

    ignore the precomplete file at least for now
    
    Change-Id: I997bdc38f705d7536a99a168815ece93dcf0c0de

diff --git a/bin/update/make_incremental_update.sh b/bin/update/make_incremental_update.sh
index 7c5e10826ba8..72286f06ce8a 100755
--- a/bin/update/make_incremental_update.sh
+++ b/bin/update/make_incremental_update.sh
@@ -122,12 +122,12 @@ if test $? -ne 0 ; then
   exit 1
 fi
 
-if [ ! -f "precomplete" ]; then
-  if [ ! -f "Contents/Resources/precomplete" ]; then
-    notice "precomplete file is missing!"
-    exit 1
-  fi
-fi
+# if [ ! -f "precomplete" ]; then
+#   if [ ! -f "Contents/Resources/precomplete" ]; then
+#     notice "precomplete file is missing!"
+#     exit 1
+#   fi
+# fi
 
 list_dirs newdirs
 list_files newfiles
commit a4ce748ed4b73529ca558dc51a2fb1812eceef84
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Apr 26 01:17:50 2017 +0200

    add a script to extract and uncompress from a mar file
    
    Change-Id: I87c11b8f7d42bc438b88482a8dd3fd1512a06df8

diff --git a/bin/update/uncompress_mar.py b/bin/update/uncompress_mar.py
new file mode 100755
index 000000000000..4c5f40733d41
--- /dev/null
+++ b/bin/update/uncompress_mar.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+# Extract a mar file and uncompress the content
+
+import os
+import sys
+import subprocess
+
+def uncompress_content(file_path):
+    bzip2 = os.environ.get('BZIP2', 'bzip2')
+    file_path_compressed = file_path + ".bz2"
+    os.rename(file_path, file_path_compressed)
+    subprocess.check_call(["bzip2", "-d", file_path_compressed])
+
+def extract_mar(mar_file, target_dir):
+    mar = os.environ.get('MAR', 'mar')
+    subprocess.check_call([mar, "-C", target_dir, "-x", mar_file])
+    file_info = subprocess.check_output([mar, "-t", mar_file])
+    lines = file_info.splitlines()
+    for line in lines:
+        info = line.split()
+        # ignore header line
+        if info[2] == b'NAME':
+            continue
+
+        uncompress_content(os.path.join(target_dir, info[2].decode("utf-8")))
+
+def main():
+    if len(sys.argv) != 3:
+        print("Help: This program takes exactly two arguments pointing to a mar file and a target location")
+        sys.exit(1)
+
+    mar_file = sys.argv[1]
+    target_dir = sys.argv[2]
+    extract_mar(mar_file, target_dir)
+
+if __name__ == "__main__":
+    main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
commit 481ea020e7e7d14fdbc398da10f3ea1f1e0ebadb
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Apr 25 21:39:11 2017 +0200

    remove the split functionality from the update creation
    
    Change-Id: I036cabff089a2cf464c887ee78b702637cce08b0

diff --git a/bin/update/create_full_mar.py b/bin/update/create_full_mar.py
index 25e654c9cd8b..ebe2a01cd2cf 100755
--- a/bin/update/create_full_mar.py
+++ b/bin/update/create_full_mar.py
@@ -38,10 +38,6 @@ def main():
 
     uncompress_dir = uncompress_file_to_dir(tar_file, temp_dir)
 
-    # on linux we should stip the symbols from the libraries
-    if sys.platform.startswith('linux'):
-        subprocess.call('strip -g ' + os.path.join(uncompress_dir, 'program/') + '*', shell=True)
-
     mar_executable = os.environ.get('MAR', 'mar')
     mar_file = make_mar_name(target_dir, filename_prefix)
     subprocess.call([os.path.join(current_dir_path, 'make_full_update.sh'), mar_file, uncompress_dir])
commit 28647a62fd3170aa718e88aa38e1079c45020533
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Apr 25 21:29:09 2017 +0200

    add a way to strip symbols from the tarballs
    
    Change-Id: I682dcc9c366efea2be00b738f630a82b4cf9d636

diff --git a/solenv/bin/modules/installer/environment.pm b/solenv/bin/modules/installer/environment.pm
index 8e5f61e1d052..8afe3c12c782 100644
--- a/solenv/bin/modules/installer/environment.pm
+++ b/solenv/bin/modules/installer/environment.pm
@@ -123,6 +123,7 @@ sub set_global_environment_variables
     if ( $ENV{'DONTCOMPRESS'} ) { $installer::globals::solarisdontcompress = 1; }
     if ( $ENV{'IGNORE_ERROR_IN_LOGFILE'} ) { $installer::globals::ignore_error_in_logfile = 1; }
     if (( $ENV{'DISABLE_STRIP'} ) && ( $ENV{'DISABLE_STRIP'} ne '' )) { $installer::globals::strip = 0; }
+    if (( $ENV{'ENABLE_STRIP'} ) && ( $ENV{'ENABLE_STRIP'} ne '' )) { $installer::globals::strip = 1; }
 
     if ( $installer::globals::localinstalldir ) { $installer::globals::localinstalldirset = 1; }
     # Special handling, if LOCALINSTALLDIR contains "~" in the path
commit 38fea5272a471bcfa60a0e917dd31d5a7dcbe70d
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Apr 25 20:41:15 2017 +0200

    start working on the creation of partial update files
    
    Change-Id: I13a70e0b12090a7e23529bc35240cefc13d17779

diff --git a/bin/update/create_partial_update.py b/bin/update/create_partial_update.py
new file mode 100755
index 000000000000..90c2abd697e3
--- /dev/null
+++ b/bin/update/create_partial_update.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+import requests
+import json
+import sys
+import hashlib
+import os
+import subprocess
+import errno
+
+from config import parse_config
+
+BUF_SIZE = 1024
+current_dir_path = os.path.dirname(os.path.realpath(__file__))
+
+def download_file(filepath, url, hash_string):
+    with open(filepath, "wb") as f:
+        response = requests.get(url, stream=True)
+
+        if not response.ok:
+            return
+
+        for block in response.iter_content(1024):
+            f.write(block)
+
+    with open(filepath, "rb") as f:
+        sha512 = hashlib.sha512()
+        while True:
+            data = f.read(BUF_SIZE)
+            if not data:
+                break
+            sha512.update(data)
+        file_hash = sha512.hexdigest()
+
+    if file_hash != hash_string:
+        pass
+
+def mkdir_p(path):
+    try:
+        os.makedirs(path)
+    except OSError as exc:  # Python >2.5
+        if exc.errno == errno.EEXIST and os.path.isdir(path):
+            pass
+        else:
+            raise
+
+def handle_language(lang_entries, filedir):
+    mar = os.environ.get('MAR', 'mar')
+    langs = {}
+    for lang, data in lang_entries.items():
+        lang_dir = os.path.join(filedir, lang)
+        lang_file = os.path.join(lang_dir, "lang.mar")
+        mkdir_p(lang_dir)
+        download_file(lang_file , data["url"], data["hash"])
+        dir_path = os.path.join(lang_dir, "lang")
+        mkdir_p(dir_path)
+        subprocess.call([mar, "-C", dir_path, "-x", lang_file])
+        langs[lang] = dir_path
+
+    return langs
+
+def download_mar_for_update_channel_and_platform(config, platform, temp_dir):
+    mar = os.environ.get('MAR', 'mar')
+    base_url = "http://updater.libreofficecrash.org/update/partial-targets/1/"
+    url = base_url + platform + "/" + config.channel
+    r = requests.get(url)
+    if r.status_code is not 200:
+        print(r.content)
+        raise Exception("download failed")
+
+    update_info = json.loads(r.content.decode("utf-8"))
+    update_files = update_info['updates']
+    downloaded_updates = {}
+    for update_file in update_files:
+        build = update_file["build"]
+        filedir = temp_dir + build
+
+        mkdir_p(filedir)
+
+        filepath = filedir + "/complete.mar"
+        url = update_file["update"]["url"]
+        expected_hash = update_file["update"]["hash"]
+        download_file(filepath, url, expected_hash)
+
+        dir_path = os.path.join(filedir, "complete")
+        mkdir_p(dir_path)
+        subprocess.call([mar, "-C", dir_path, "-x", filepath])
+
+        downloaded_updates[build] = {"complete": dir_path}
+
+        langs = handle_language(update_file["languages"], filedir)
+        downloaded_updates[build]["languages"] = langs
+
+    return downloaded_updates
+
+def generate_file_name(current_build_id, old_build_id, mar_name_prefix):
+    name = "%s_from_%s_to_%s_partial.mar" %(mar_name_prefix, current_build_id, old_build_id)
+    return name
+
+def generate_lang_file_name(current_build_id, old_build_id, mar_name_prefix, lang):
+    name = "%s_%s_from_%s_to_%s_partial.mar" %(mar_name_prefix, lang, current_build_id, old_build_id)
+    return name
+
+def main():
+    product_name = sys.argv[1]
+    workdir = sys.argv[2]
+    update_dir = sys.argv[3]
+    temp_dir = sys.argv[4]
+    mar_name_prefix = sys.argv[5]
+    update_config = sys.argv[6]
+    platform = sys.argv[7]
+    current_build_path = sys.argv[8]
+    build_id = sys.argv[9]
+    dir_name =  [os.path.join(current_build_path, name) for name in os.listdir(current_build_path) if os.path.isdir(os.path.join(current_build_path, name))]
+    current_build_path = dir_name[0]
+
+    config = parse_config(update_config)
+
+    updates = download_mar_for_update_channel_and_platform(config, platform, temp_dir)
+
+    print(updates)
+    for build, update in updates.items():
+        file_name = generate_file_name(build_id, build, mar_name_prefix)
+        mar_file = os.path.join(temp_dir, build, file_name)
+        print(mar_file)
+        print(current_build_path)
+        print(update["complete"])
+        subprocess.call([os.path.join(current_dir_path, 'make_incremental_update.sh'), mar_file, current_build_path, update["complete"]])
+        for lang in update["languages"].items():
+            lang_name = generate_lang_file_name(build_id, build, mar_name_prefix, lang)
+            lang_mar_file = os.path.join(temp_dir, build, lang_name)
+            #subprocess.call([os.path.join(current_dir_path, 'make_incremental_update.sh'), mar_file, current_build_path, update["complete"]])
+
+
+if __name__ == '__main__':
+    main()
commit bf5e1cc1f984dfc23e0f85fae37a62303de59546
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Apr 25 20:40:05 2017 +0200

    add mbsdiff as build executable
    
    Change-Id: I68c9b14937c219ee142386b72047a6995d004f47

diff --git a/Repository.mk b/Repository.mk
index 3a14db3da0db..ce0cac09af6f 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -43,6 +43,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
 	lngconvex \
 	localize \
 	makedepend \
+	mbsdiff \
 	mork_helper \
 	osl_process_child \
 	pdf2xml \
diff --git a/onlineupdate/Executable_mbsdiff.mk b/onlineupdate/Executable_mbsdiff.mk
new file mode 100644
index 000000000000..e5a49b5ac747
--- /dev/null
+++ b/onlineupdate/Executable_mbsdiff.mk
@@ -0,0 +1,36 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,mbsdiff))
+
+$(eval $(call gb_Executable_set_include,mbsdiff,\
+	-I$(SRCDIR)/onlineupdate/inc \
+	$$(INCLUDE) \
+))
+
+$(eval $(call gb_Executable_use_externals,mbsdiff,\
+	bzip2 \
+))
+
+
+ifeq ($(OS),WNT)
+$(eval $(call gb_Executable_add_libs,mbsdiff,\
+    ws2_32.lib \
+))
+endif
+
+$(eval $(call gb_Executable_add_defs,mbsdiff,\
+	-DUNICODE \
+))
+
+$(eval $(call gb_Executable_add_cxxobjects,mbsdiff,\
+	onlineupdate/source/mbsdiff/bsdiff \
+))
+
+# vim:set shiftwidth=4 tabstop=4 noexpandtab: */
diff --git a/onlineupdate/Module_onlineupdate.mk b/onlineupdate/Module_onlineupdate.mk
index e84a208e79b3..dfb8d54ef70c 100644
--- a/onlineupdate/Module_onlineupdate.mk
+++ b/onlineupdate/Module_onlineupdate.mk
@@ -20,6 +20,7 @@ $(eval $(call gb_Module_add_targets,onlineupdate,\
 		StaticLibrary_winhelper )\
 	Executable_mar \
 	Executable_updater \
+	Executable_mbsdiff \
 ))
 endif
 
diff --git a/onlineupdate/source/update/updater/bspatch.h b/onlineupdate/inc/bspatch.h
similarity index 100%
rename from onlineupdate/source/update/updater/bspatch.h
rename to onlineupdate/inc/bspatch.h
diff --git a/onlineupdate/source/mbsdiff/bsdiff.cxx b/onlineupdate/source/mbsdiff/bsdiff.cxx
new file mode 100644
index 000000000000..ef80bd99770f
--- /dev/null
+++ b/onlineupdate/source/mbsdiff/bsdiff.cxx
@@ -0,0 +1,405 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+  bsdiff.c -- Binary patch generator.
+
+  Copyright 2003 Colin Percival
+
+  For the terms under which this work may be distributed, please see
+  the adjoining file "LICENSE".
+
+  ChangeLog:
+  2005-05-05 - Use the modified header struct from bspatch.h; use 32-bit
+               values throughout.
+                 --Benjamin Smedberg <benjamin at smedbergs.us>
+  2005-05-18 - Use the same CRC algorithm as bzip2, and leverage the CRC table
+               provided by libbz2.
+                 --Darin Fisher <darin at meer.net>
+*/
+
+#include "bspatch.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#ifdef XP_WIN
+#include <io.h>
+#include <winsock2.h>
+#else
+#include <unistd.h>
+#include <arpa/inet.h>
+#define _O_BINARY 0
+#endif
+
+#undef MIN
+#define MIN(x,y) (((x)<(y)) ? (x) : (y))
+
+/*---------------------------------------------------------------------------*/
+
+/* This variable lives in libbz2.  It's declared in bzlib_private.h, so we just
+ * declare it here to avoid including that entire header file.
+ */
+extern "C"  unsigned int BZ2_crc32Table[256];
+
+static unsigned int
+crc32(const unsigned char *buf, unsigned int len)
+{
+    unsigned int crc = 0xffffffffL;
+
+    const unsigned char *end = buf + len;
+    for (; buf != end; ++buf)
+        crc = (crc << 8) ^ BZ2_crc32Table[(crc >> 24) ^ *buf];
+
+    crc = ~crc;
+    return crc;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+reporterr(int e, const char *fmt, ...)
+{
+    if (fmt) {
+        va_list args;
+        va_start(args, fmt);
+        vfprintf(stderr, fmt, args);
+        va_end(args);
+    }
+
+    exit(e);
+}
+
+static void
+split(int32_t *I,int32_t *V,int32_t start,int32_t len,int32_t h)
+{
+    int32_t i,j,k,x,tmp,jj,kk;
+
+    if(len<16) {
+        for(k=start;k<start+len;k+=j) {
+            j=1;x=V[I[k]+h];
+            for(i=1;k+i<start+len;i++) {
+                if(V[I[k+i]+h]<x) {
+                    x=V[I[k+i]+h];
+                    j=0;
+                };
+                if(V[I[k+i]+h]==x) {
+                    tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
+                    j++;
+                };
+            };
+            for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
+            if(j==1) I[k]=-1;
+        };
+        return;
+    };
+
+    x=V[I[start+len/2]+h];
+    jj=0;kk=0;
+    for(i=start;i<start+len;i++) {
+        if(V[I[i]+h]<x) jj++;
+        if(V[I[i]+h]==x) kk++;
+    };
+    jj+=start;kk+=jj;
+
+    i=start;j=0;k=0;
+    while(i<jj) {
+        if(V[I[i]+h]<x) {
+            i++;
+        } else if(V[I[i]+h]==x) {
+            tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
+            j++;
+        } else {
+            tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
+            k++;
+        };
+    };
+
+    while(jj+j<kk) {
+        if(V[I[jj+j]+h]==x) {
+            j++;
+        } else {
+            tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
+            k++;
+        };
+    };
+
+    if(jj>start) split(I,V,start,jj-start,h);
+
+    for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
+    if(jj==kk-1) I[jj]=-1;
+
+    if(start+len>kk) split(I,V,kk,start+len-kk,h);
+}
+
+static void
+qsufsort(int32_t *I,int32_t *V,unsigned char *old,int32_t oldsize)
+{
+    int32_t buckets[256];
+    int32_t i,h,len;
+
+    for(i=0;i<256;i++) buckets[i]=0;
+    for(i=0;i<oldsize;i++) buckets[old[i]]++;
+    for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
+    for(i=255;i>0;i--) buckets[i]=buckets[i-1];
+    buckets[0]=0;
+
+    for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
+    I[0]=oldsize;
+    for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
+    V[oldsize]=0;
+    for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
+    I[0]=-1;
+
+    for(h=1;I[0]!=-(oldsize+1);h+=h) {
+        len=0;
+        for(i=0;i<oldsize+1;) {
+            if(I[i]<0) {
+                len-=I[i];
+                i-=I[i];
+            } else {
+                if(len) I[i-len]=-len;
+                len=V[I[i]]+1-i;
+                split(I,V,i,len,h);
+                i+=len;
+                len=0;
+            };
+        };
+        if(len) I[i-len]=-len;
+    };
+
+    for(i=0;i<oldsize+1;i++) I[V[i]]=i;
+}
+
+static int32_t
+matchlen(unsigned char *old,int32_t oldsize,unsigned char *newbuf,int32_t newsize)
+{
+    int32_t i;
+
+    for(i=0;(i<oldsize)&&(i<newsize);i++)
+        if(old[i]!=newbuf[i]) break;
+
+    return i;
+}
+
+static int32_t
+search(int32_t *I,unsigned char *old,int32_t oldsize,
+       unsigned char *newbuf,int32_t newsize,int32_t st,int32_t en,int32_t *pos)
+{
+    int32_t x,y;
+
+    if(en-st<2) {
+        x=matchlen(old+I[st],oldsize-I[st],newbuf,newsize);
+        y=matchlen(old+I[en],oldsize-I[en],newbuf,newsize);
+
+        if(x>y) {
+            *pos=I[st];
+            return x;
+        } else {
+            *pos=I[en];
+            return y;
+        }
+    };
+
+    x=st+(en-st)/2;
+    if(memcmp(old+I[x],newbuf,MIN(oldsize-I[x],newsize))<0) {
+        return search(I,old,oldsize,newbuf,newsize,x,en,pos);
+    } else {
+        return search(I,old,oldsize,newbuf,newsize,st,x,pos);
+    };
+}
+
+int main(int argc,char *argv[])
+{
+    int fd;
+    unsigned char *old,*newbuf;
+    int32_t oldsize,newsize;
+    int32_t *I,*V;
+
+    int32_t scan,pos,len;
+    int32_t lastscan,lastpos,lastoffset;
+    int32_t oldscore,scsc;
+
+    int32_t s,Sf,lenf,Sb,lenb;
+    int32_t overlap,Ss,lens;
+    int32_t i;
+
+    int32_t dblen,eblen;
+    unsigned char *db,*eb;
+
+    unsigned int scrc;
+
+    MBSPatchHeader header = {
+        {'M','B','D','I','F','F','1','0'},
+        0, 0, 0, 0, 0, 0
+    };
+
+    uint32_t numtriples;
+
+    if(argc!=4)
+        reporterr(1,"usage: %s <oldfile> <newfile> <patchfile>\n",argv[0]);
+
+    /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
+        that we never try to malloc(0) and get a NULL pointer */
+    if(((fd=open(argv[1],O_RDONLY|_O_BINARY,0))<0) ||
+        ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+        ((old=(unsigned char*) malloc(oldsize+1))==NULL) ||
+        (lseek(fd,0,SEEK_SET)!=0) ||
+        (read(fd,old,oldsize)!=oldsize) ||
+        (close(fd)==-1))
+        reporterr(1,"%s\n",argv[1]);
+
+    scrc = crc32(old, oldsize);
+
+    if(((I=(int32_t*) malloc((oldsize+1)*sizeof(int32_t)))==NULL) ||
+        ((V=(int32_t*) malloc((oldsize+1)*sizeof(int32_t)))==NULL))
+        reporterr(1,NULL);
+
+    qsufsort(I,V,old,oldsize);
+
+    free(V);
+
+    /* Allocate newsize+1 bytes instead of newsize bytes to ensure
+        that we never try to malloc(0) and get a NULL pointer */
+    if(((fd=open(argv[2],O_RDONLY|_O_BINARY,0))<0) ||
+        ((newsize=lseek(fd,0,SEEK_END))==-1) ||
+        ((newbuf=(unsigned char*) malloc(newsize+1))==NULL) ||
+        (lseek(fd,0,SEEK_SET)!=0) ||
+        (read(fd,newbuf,newsize)!=newsize) ||
+        (close(fd)==-1)) reporterr(1,"%s\n",argv[2]);
+
+    if(((db=(unsigned char*) malloc(newsize+1))==NULL) ||
+        ((eb=(unsigned char*) malloc(newsize+1))==NULL))
+        reporterr(1,NULL);
+
+    dblen=0;
+    eblen=0;
+
+    if((fd=open(argv[3],O_CREAT|O_TRUNC|O_WRONLY|_O_BINARY,0666))<0)
+        reporterr(1,"%s\n",argv[3]);
+
+    /* start writing here */
+
+    /* We don't know the lengths yet, so we will write the header again
+         at the end */
+
+    if(write(fd,&header,sizeof(MBSPatchHeader))!=sizeof(MBSPatchHeader))
+        reporterr(1,"%s\n",argv[3]);
+
+    scan=0;len=0;
+    lastscan=0;lastpos=0;lastoffset=0;
+    numtriples = 0;
+    while(scan<newsize) {
+        oldscore=0;
+
+        for(scsc=scan+=len;scan<newsize;scan++) {
+            len=search(I,old,oldsize,newbuf+scan,newsize-scan,
+                    0,oldsize,&pos);
+
+            for(;scsc<scan+len;scsc++)
+            if((scsc+lastoffset<oldsize) &&
+                (old[scsc+lastoffset] == newbuf[scsc]))
+                oldscore++;
+
+            if(((len==oldscore) && (len!=0)) ||
+                (len>oldscore+8)) break;
+
+            if((scan+lastoffset<oldsize) &&
+                (old[scan+lastoffset] == newbuf[scan]))
+                oldscore--;
+        };
+
+        if((len!=oldscore) || (scan==newsize)) {
+            MBSPatchTriple triple;
+
+            s=0;Sf=0;lenf=0;
+            for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
+                if(old[lastpos+i]==newbuf[lastscan+i]) s++;
+                i++;
+                if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
+            };
+
+            lenb=0;
+            if(scan<newsize) {
+                s=0;Sb=0;
+                for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
+                    if(old[pos-i]==newbuf[scan-i]) s++;
+                    if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
+                };
+            };
+
+            if(lastscan+lenf>scan-lenb) {
+                overlap=(lastscan+lenf)-(scan-lenb);
+                s=0;Ss=0;lens=0;
+                for(i=0;i<overlap;i++) {
+                    if(newbuf[lastscan+lenf-overlap+i]==
+                       old[lastpos+lenf-overlap+i]) s++;
+                    if(newbuf[scan-lenb+i]==
+                       old[pos-lenb+i]) s--;
+                    if(s>Ss) { Ss=s; lens=i+1; };
+                };
+
+                lenf+=lens-overlap;
+                lenb-=lens;
+            };
+
+            for(i=0;i<lenf;i++)
+                db[dblen+i]=newbuf[lastscan+i]-old[lastpos+i];
+            for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
+                eb[eblen+i]=newbuf[lastscan+lenf+i];
+
+            dblen+=lenf;
+            eblen+=(scan-lenb)-(lastscan+lenf);
+
+            triple.x = htonl(lenf);
+            triple.y = htonl((scan-lenb)-(lastscan+lenf));
+            triple.z = htonl((pos-lenb)-(lastpos+lenf));
+            if (write(fd,&triple,sizeof(triple)) != sizeof(triple))
+                reporterr(1,NULL);
+
+#ifdef DEBUG_bsmedberg
+            printf("Writing a block:\n"
+                   "    X: %u\n"
+                   "    Y: %u\n"
+                   "    Z: %i\n",
+                   (uint32_t) lenf,
+                   (uint32_t) ((scan-lenb)-(lastscan+lenf)),
+                   (uint32_t) ((pos-lenb)-(lastpos+lenf)));
+#endif
+
+            ++numtriples;
+
+            lastscan=scan-lenb;
+            lastpos=pos-lenb;
+            lastoffset=pos-scan;
+        };
+    };
+
+    if(write(fd,db,dblen)!=dblen)
+        reporterr(1,NULL);
+
+    if(write(fd,eb,eblen)!=eblen)
+        reporterr(1,NULL);
+
+    header.slen    = htonl(oldsize);
+    header.scrc32    = htonl(scrc);
+    header.dlen    = htonl(newsize);
+    header.cblen    = htonl(numtriples * sizeof(MBSPatchTriple));
+    header.difflen    = htonl(dblen);
+    header.extralen = htonl(eblen);
+
+    if (lseek(fd,0,SEEK_SET) == -1 ||
+        write(fd,&header,sizeof(header)) != sizeof(header) ||
+        close(fd) == -1)
+        reporterr(1,NULL);
+
+    free(db);
+    free(eb);
+    free(I);
+    free(old);
+    free(newbuf);
+
+    return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 7705ba39ac796ecbdfee0e53f88308b256c8f1c7
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Apr 24 23:57:22 2017 +0200

    actually abort the update process if the update file is invalid
    
    Change-Id: I724e50d1e74228f0be00b9b6376c3d074db5c9ed

diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index 1d3b0acc9158..cad36200daaa 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -287,6 +287,40 @@ class invalid_update_info : public std::exception
 {
 };
 
+class invalid_hash : public std::exception
+{
+    OString maMessage;
+public:
+
+    invalid_hash(const OUString& rExpectedHash, const OUString& rReceivedHash)
+    {
+        OUString aMsg = "Invalid hash found.\nExpected: " + rExpectedHash + ";\nReceived: " + rReceivedHash;
+        maMessage = OUStringToOString(aMsg, RTL_TEXTENCODING_UTF8);
+    }
+
+    const char* what() const noexcept override
+    {
+        return maMessage.getStr();
+    }
+};
+
+class invalid_size : public std::exception
+{
+    OString maMessage;
+public:
+
+    invalid_size(const size_t nExpectedSize, const size_t nReceivedSize)
+    {
+        OUString aMsg = "Invalid file size found.\nExpected: " + OUString::number(nExpectedSize) + ";\nReceived: " + OUString::number(nReceivedSize);
+        maMessage = OUStringToOString(aMsg, RTL_TEXTENCODING_UTF8);
+    }
+
+    const char* what() const noexcept override
+    {
+        return maMessage.getStr();
+    }
+};
+
 OUString toOUString(const std::string& rStr)
 {
     return OUString::fromUtf8(rStr.c_str());
@@ -538,11 +572,13 @@ void download_file(const OUString& rURL, size_t nFileSize, const OUString& rHash
     if (nSize != nFileSize)
     {
         SAL_WARN("desktop.updater", "File sizes don't match. File might be corrupted.");
+        throw invalid_size(nFileSize, nSize);
     }
 
     if (aHash != rHash)
     {
         SAL_WARN("desktop.updater", "File hash don't match. File might be corrupted.");
+        throw invalid_hash(rHash, aHash);
     }
 
     OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/");
@@ -600,6 +636,14 @@ void update_checker()
     {
         SAL_WARN("desktop.updater", "error during the update check");
     }
+    catch (const invalid_size& e)
+    {
+        SAL_WARN("desktop.updater", e.what());
+    }
+    catch (const invalid_hash& e)
+    {
+        SAL_WARN("desktop.updater", e.what());
+    }
     catch (...)
     {
         SAL_WARN("desktop.updater", "unknown error during the update check");
commit da9354668978381efe65589a836390d2e24d54d3
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Apr 24 23:25:44 2017 +0200

    actually check the hash of the update files
    
    Change-Id: I98a5f8904a35cb167e87d6c5c11bcf133115cbc1

diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index 388c45e7211e..1d3b0acc9158 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -31,6 +31,7 @@
 #include <orcus/json_document_tree.hpp>
 #include <orcus/config.hpp>
 #include <orcus/pstring.hpp>
+#include <comphelper/hash.hxx>
 
 namespace {
 
@@ -280,18 +281,6 @@ static size_t WriteCallback(void *ptr, size_t size,
   return real_size;
 }
 
-// Callback to get the response data from server to a file.
-static size_t WriteCallbackFile(void *ptr, size_t size,
-                            size_t nmemb, void *userp)
-{
-  if (!userp)
-    return 0;
-
-  SvStream* response = static_cast<SvStream *>(userp);
-  size_t real_size = size * nmemb;
-  response->WriteBytes(static_cast<char *>(ptr), real_size);
-  return real_size;
-}
 
 
 class invalid_update_info : public std::exception
@@ -408,7 +397,45 @@ update_info parse_response(const std::string& rResponse)
     return aUpdateInfo;
 }
 
-std::string download_content(const OString& rURL, bool bFile)
+struct WriteDataFile
+{
+    comphelper::Hash maHash;
+    SvStream* mpStream;
+
+    WriteDataFile(SvStream* pStream):
+        maHash(comphelper::HashType::SHA512),
+        mpStream(pStream)
+    {
+    }
+
+    OUString getHash()
+    {
+        auto final_hash = maHash.finalize();
+        std::stringstream aStrm;
+        for (auto& i: final_hash)
+        {
+            aStrm << std::setw(2) << std::setfill('0') << std::hex << (int)i;
+        }
+
+        return toOUString(aStrm.str());
+    }
+};
+
+// Callback to get the response data from server to a file.
+size_t WriteCallbackFile(void *ptr, size_t size,
+                            size_t nmemb, void *userp)
+{
+  if (!userp)
+    return 0;
+
+  WriteDataFile* response = static_cast<WriteDataFile *>(userp);
+  size_t real_size = size * nmemb;
+  response->mpStream->WriteBytes(static_cast<char *>(ptr), real_size);
+  response->maHash.update(static_cast<const unsigned char*>(ptr), real_size);
+  return real_size;
+}
+
+std::string download_content(const OString& rURL, bool bFile, OUString& rHash)
 {
     CURL* curl = curl_easy_init();
 
@@ -434,6 +461,7 @@ std::string download_content(const OString& rURL, bool bFile)
 
     std::string response_body;
     utl::TempFile aTempFile;
+    WriteDataFile aFile(aTempFile.GetStream(StreamMode::WRITE));
     if (!bFile)
     {
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
@@ -452,7 +480,7 @@ std::string download_content(const OString& rURL, bool bFile)
 
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallbackFile);
         curl_easy_setopt(curl, CURLOPT_WRITEDATA,
-                static_cast<void *>(aTempFile.GetStream(StreamMode::WRITE)));
+                static_cast<void *>(&aFile));
     }
 
     // Fail if 400+ is returned from the web server.
@@ -473,12 +501,10 @@ std::string download_content(const OString& rURL, bool bFile)
         throw error_updater();
     }
 
-    return response_body;
-}
+    if (bFile)
+        rHash = aFile.getHash();
 
-OUString generateHash(const OUString& /*rURL*/)
-{
-    return OUString();
+    return response_body;
 }
 
 void handle_file_error(osl::FileBase::RC eError)
@@ -496,7 +522,8 @@ void handle_file_error(osl::FileBase::RC eError)
 void download_file(const OUString& rURL, size_t nFileSize, const OUString& rHash, const OUString& aFileName)
 {
     OString aURL = OUStringToOString(rURL, RTL_TEXTENCODING_UTF8);
-    std::string temp_file = download_content(aURL, true);
+    OUString aHash;
+    std::string temp_file = download_content(aURL, true, aHash);
     if (temp_file.empty())
         throw error_updater();
 
@@ -513,7 +540,6 @@ void download_file(const OUString& rURL, size_t nFileSize, const OUString& rHash
         SAL_WARN("desktop.updater", "File sizes don't match. File might be corrupted.");
     }
 
-    OUString aHash = generateHash(aTempFile);
     if (aHash != rHash)
     {
         SAL_WARN("desktop.updater", "File hash don't match. File might be corrupted.");
@@ -548,7 +574,8 @@ void update_checker()
 
     try
     {
-        std::string response_body = download_content(aURL, false);
+        OUString aHash;
+        std::string response_body = download_content(aURL, false, aHash);
         if (!response_body.empty())
         {
             update_info aUpdateInfo = parse_response(response_body);
commit c2b34cfd0888c7d1fa23a84ccf617ab388180443
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Apr 24 19:51:40 2017 +0200

    if the update_dir does not exist continue with the update check

diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index c7b6ba16ce57..3da1d48617ac 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -1471,16 +1471,12 @@ int Desktop::Main()
         {
             osl::DirectoryItem aPatchInfo;
             osl::DirectoryItem::get(Updater::getUpdateInfoURL(), aPatchInfo);
+            osl::DirectoryItem aDirectoryItem;
+            osl::DirectoryItem::get(Updater::getUpdateDirURL(), aDirectoryItem);
 
-            if (aPatchInfo.is())
+            if (aPatchInfo.is() && aDirectoryItem.is())
             {
-                osl::DirectoryItem aDirectoryItem;
-                osl::DirectoryItem::get(Updater::getUpdateDirURL(), aDirectoryItem);
-                bool bValidUpdateDirExists = aDirectoryItem.is();
-                if (bValidUpdateDirExists)
-                {
-                    update();
-                }
+                update();
             }
             else if (isTimeForUpdateCheck())
             {
commit 45321202b7e4efdf6dca1f9b64ba8adac81f8deb
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Apr 24 18:54:59 2017 +0200

    better reporting for normal response from updater
    
    Change-Id: I26cbd69c46afadc21eeab73cbccddc6873c43655

diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index a0e0e3bf4f6f..388c45e7211e 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -194,6 +194,7 @@ struct update_info
 {
     OUString aFromBuildID;
     OUString aSeeAlsoURL;
+    OUString aMessage;
 
     update_file aUpdateFile;
     std::vector<language_file> aLanguageFiles;
@@ -356,6 +357,13 @@ update_info parse_response(const std::string& rResponse)
     {
         throw invalid_update_info();
     }
+    else if (std::find(aRootKeys.begin(), aRootKeys.end(), "response") != aRootKeys.end())
+    {
+        update_info aUpdateInfo;
+        auto aMsgNode = aDocumentRoot.child("response");
+        aUpdateInfo.aMessage = toOUString(aMsgNode.string_value().str());
+        return aUpdateInfo;
+    }
 
     orcus::json::detail::node aFromNode = aDocumentRoot.child("from");
     if (aFromNode.type() != orcus::json_node_t::string)
@@ -544,8 +552,17 @@ void update_checker()
         if (!response_body.empty())
         {
             update_info aUpdateInfo = parse_response(response_body);
-            download_file(aUpdateInfo.aUpdateFile.aURL, aUpdateInfo.aUpdateFile.nSize, aUpdateInfo.aUpdateFile.aHash, "update.mar");
-            CreateValidUpdateDir(aUpdateInfo);
+            if (aUpdateInfo.aUpdateFile.aURL.isEmpty())
+            {
+                // No update currently available
+                // add entry to updating.log with the message
+                SAL_WARN("desktop.updater", "Message received from the updater: " << aUpdateInfo.aMessage);
+            }
+            else
+            {
+                download_file(aUpdateInfo.aUpdateFile.aURL, aUpdateInfo.aUpdateFile.nSize, aUpdateInfo.aUpdateFile.aHash, "update.mar");
+                CreateValidUpdateDir(aUpdateInfo);
+            }
         }
     }
     catch (const invalid_update_info&)
commit cef01f8b686b2ac134cfe195159e2f0f7e2934c2
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Apr 24 01:14:53 2017 +0200

    extract the common updater path info into methods
    
    Change-Id: I8d25fc3c6a6a0a7e05bac6679f2312a904e75bbd

diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index a43acbb77d62..c7b6ba16ce57 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -1469,19 +1469,13 @@ int Desktop::Main()
 #if HAVE_FEATURE_UPDATE_MAR
         if (officecfg::Office::Update::Update::Enabled::get())
         {
-            OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/");
-            rtl::Bootstrap::expandMacros(aPatchDirURL);
-
             osl::DirectoryItem aPatchInfo;
-            osl::DirectoryItem::get(aPatchDirURL + "/update.info", aPatchInfo);
+            osl::DirectoryItem::get(Updater::getUpdateInfoURL(), aPatchInfo);
 
             if (aPatchInfo.is())
             {
-                OUString aInstallationDir( "$BRAND_BASE_DIR/");
-                rtl::Bootstrap::expandMacros(aInstallationDir);
-
                 osl::DirectoryItem aDirectoryItem;
-                osl::DirectoryItem::get(aInstallationDir + "/updated", aDirectoryItem);
+                osl::DirectoryItem::get(Updater::getUpdateDirURL(), aDirectoryItem);
                 bool bValidUpdateDirExists = aDirectoryItem.is();
                 if (bValidUpdateDirExists)
                 {
diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index e82e84f41bc6..a0e0e3bf4f6f 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -140,7 +140,7 @@ char** createCommandLine()
     }
     {
         // directory with the patch log

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list