[Libreoffice-commits] core.git: 159 commits - bin/update config_host/config_features.h.in config_host.mk.in configure.ac desktop/CppunitTest_desktop_app.mk desktop/inc desktop/Library_crashreport.mk desktop/Library_sofficeapp.mk desktop/source include/onlineupdate Makefile.gbuild Makefile.in 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 postprocess/CustomTarget_registry.mk Repository.mk solenv/bin vcl/unx

Markus Mohrhard markus.mohrhard at googlemail.com
Fri May 19 01:44:35 UTC 2017


 Makefile.gbuild                                                          |   28 
 Makefile.in                                                              |   17 
 Repository.mk                                                            |   14 
 bin/update/common.sh                                                     |  205 
 bin/update/config.py                                                     |   25 
 bin/update/create_build_config.py                                        |   50 
 bin/update/create_full_mar.py                                            |   54 
 bin/update/create_full_mar_for_languages.py                              |   66 
 bin/update/create_partial_update.py                                      |  155 
 bin/update/make_full_update.sh                                           |  121 
 bin/update/make_incremental_update.sh                                    |  317 
 bin/update/path.py                                                       |   52 
 bin/update/signing.py                                                    |   11 
 bin/update/tools.py                                                      |   55 
 bin/update/uncompress_mar.py                                             |   48 
 bin/update/upload_build_config.py                                        |   42 
 bin/update/upload_builds.py                                              |   31 
 config_host.mk.in                                                        |    1 
 config_host/config_features.h.in                                         |    5 
 configure.ac                                                             |    8 
 desktop/CppunitTest_desktop_app.mk                                       |    4 
 desktop/Library_crashreport.mk                                           |    2 
 desktop/Library_sofficeapp.mk                                            |    6 
 desktop/inc/app.hxx                                                      |    3 
 desktop/source/app/app.cxx                                               |   45 
 desktop/source/app/updater.cxx                                           |  723 +
 desktop/source/app/updater.hxx                                           |   37 
 dev/null                                                                 |binary
 include/onlineupdate/mar_private.h                                       |    2 
 officecfg/files.mk                                                       |    1 
 officecfg/registry/schema/org/openoffice/Office/Update.xcs               |   52 
 onlineupdate/CustomTarget_generated.mk                                   |   30 
 onlineupdate/Executable_mar.mk                                           |   19 
 onlineupdate/Executable_mbsdiff.mk                                       |   36 
 onlineupdate/Executable_update_service.mk                                |   61 
 onlineupdate/Executable_updater.mk                                       |   30 
 onlineupdate/Module_onlineupdate.mk                                      |    7 
 onlineupdate/README                                                      |    5 
 onlineupdate/StaticLibrary_libmar.mk                                     |   10 
 onlineupdate/StaticLibrary_updatehelper.mk                               |   32 
 onlineupdate/StaticLibrary_winhelper.mk                                  |   22 
 onlineupdate/WinResTarget_updater.mk                                     |   15 
 onlineupdate/astyle.options                                              |    7 
 onlineupdate/inc/bspatch.h                                               |   46 
 onlineupdate/inc/types.hxx                                               |   25 
 onlineupdate/inc/winhelper/windowsStart.hxx                              |   23 
 onlineupdate/source/libmar/sign/mar_sign.c                               |    2 
 onlineupdate/source/libmar/sign/nss_secutil.h                            |   18 
 onlineupdate/source/libmar/src/mar_read.c                                |    2 
 onlineupdate/source/libmar/tool/mar.c                                    |   48 
 onlineupdate/source/libmar/verify/cryptox.c                              |    9 
 onlineupdate/source/libmar/verify/cryptox.h                              |   12 
 onlineupdate/source/mbsdiff/bsdiff.cxx                                   |  405 
 onlineupdate/source/service/certificatecheck.cxx                         |  292 
 onlineupdate/source/service/certificatecheck.hxx                         |   22 
 onlineupdate/source/service/maintenanceservice.cxx                       |  438 
 onlineupdate/source/service/maintenanceservice.hxx                       |   10 
 onlineupdate/source/service/registrycertificates.cxx                     |  181 
 onlineupdate/source/service/registrycertificates.hxx                     |   13 
 onlineupdate/source/service/resource.hxx                                 |   20 
 onlineupdate/source/service/servicebase.cxx                              |   97 
 onlineupdate/source/service/servicebase.hxx                              |   22 
 onlineupdate/source/service/serviceinstall.cxx                           |  850 +
 onlineupdate/source/service/serviceinstall.hxx                           |   21 
 onlineupdate/source/service/windowsHelper.hxx                            |   48 
 onlineupdate/source/service/workmonitor.cxx                              |  770 +
 onlineupdate/source/service/workmonitor.hxx                              |    5 
 onlineupdate/source/update/common/pathhash.cxx                           |  178 
 onlineupdate/source/update/common/readstrings.cxx                        |  315 
 onlineupdate/source/update/common/readstrings.h                          |   12 
 onlineupdate/source/update/common/uachelper.cxx                          |  261 
 onlineupdate/source/update/common/uachelper.h                            |   16 
 onlineupdate/source/update/common/updatedefines.h                        |   16 
 onlineupdate/source/update/common/updatehelper.cxx                       |  991 -
 onlineupdate/source/update/common/updatehelper.h                         |    4 
 onlineupdate/source/update/common/updatelogging.cxx                      |   71 
 onlineupdate/source/update/common/updatelogging.h                        |   40 
 onlineupdate/source/update/common/win_dirent.h                           |   18 
 onlineupdate/source/update/updater/archivereader.cxx                     |  382 
 onlineupdate/source/update/updater/archivereader.h                       |   32 
 onlineupdate/source/update/updater/bspatch.cxx                           |  230 
 onlineupdate/source/update/updater/gen_cert_header.py                    |   33 
 onlineupdate/source/update/updater/loaddlls.cxx                          |  170 
 onlineupdate/source/update/updater/master-daily.der                      |binary
 onlineupdate/source/update/updater/nsWindowsRestart.cxx                  |  577 
 onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx |   37 
 onlineupdate/source/update/updater/progressui.h                          |   17 
 onlineupdate/source/update/updater/progressui_gtk.cxx                    |  114 
 onlineupdate/source/update/updater/progressui_null.cxx                   |    4 
 onlineupdate/source/update/updater/progressui_win.cxx                    |  404 
 onlineupdate/source/update/updater/updater-common.build                  |   15 
 onlineupdate/source/update/updater/updater.cxx                           | 6419 +++++-----
 onlineupdate/source/update/updater/updater.rc                            |    2 
 onlineupdate/source/update/updater/win_dirent.cxx                        |   78 
 onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx    |  513 
 onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h      |  211 
 onlineupdate/source/winhelper/windowsStart.cxx                           |  270 
 postprocess/CustomTarget_registry.mk                                     |    1 
 solenv/bin/modules/installer/environment.pm                              |    1 
 vcl/unx/glxtest.cxx                                                      |    2 
 100 files changed, 11785 insertions(+), 5482 deletions(-)

New commits:
commit b5d72331053ce19942463ac6e688eac74e01e649
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri May 5 14:08:28 2017 +0200

    Wdeclaration-after-statement
    
    Change-Id: Ie3a34305c824e2f04feb8b1db39c0df342588c43

diff --git a/onlineupdate/source/libmar/tool/mar.c b/onlineupdate/source/libmar/tool/mar.c
index 232e4e0c220a..d67935bd559d 100644
--- a/onlineupdate/source/libmar/tool/mar.c
+++ b/onlineupdate/source/libmar/tool/mar.c
@@ -272,10 +272,11 @@ int main(int argc, char **argv) {
       while(fgets(buf, 1000, file) != NULL)
       {
         int j;
+        size_t str_len;
         for (j=strlen(buf)-1;j>=0 && (buf[j]=='\n' || buf[j]=='\r');j--)
           ;
         buf[j+1]='\0';
-        size_t str_len = strlen(buf) + 1;
+        str_len = strlen(buf) + 1;
         files[num_files] = (char*)malloc(sizeof(char)*str_len);
         strcpy(files[num_files], buf);
         ++num_files;
commit 8bd07b0c54c9e8aec4a72d8b4b954abd14403ca3
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 2c714fda72902507b3645cff7c06db8d46fdf49d
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 b1bef097e6a10a65d4d548ad4f0a771092307806
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 fcf365f352ee4daf1dd538e64d7982faff2206d4
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 a5204fe5b3a403f25a5a2781761cd2303391cf36
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 db59b84a319c3309985fbe27672e68b84d84d7ad
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 5e1d8ada02365fc32146208f19a4e2671d38dded
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 0a84291cf6aa7c700c6dcb609647b24e3855c31e
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 f8952eb7f3d6cabc8469ba0a53e05f0855527b62
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 9e10833e841f446286ab38577335d1f0a4a8c555
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 c13b1c56e57dfb0d56a3e6d726377959e1d3bd78
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 ff65b97cf29bda2a46e3a19d535d67b062a8f3fa
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 e8bcef2c53e7b9d928d4fa138d181daafbc097ad
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 ff3e72ae7351346a6086d47c22be0106e408fbb8
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 fdb4b3448944dca047f080095923a35f13c40141
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 d3c6b7ff4cc863d94a005737294026a8f9297ee1
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 a3a74db73ef9167cc886d00bb62727fdfb6f4888
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 4e8a9345150c5948655f1c04a9ddbb554db24543
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 3bde01f77ae54e8fb99783081e2bf49479168425
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 eb317fa36f9a6694c608165f9d47b354e508fc66
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 208012cf122dadacd824722c8ab7e0210d691692
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 25ea5a7a561045f8a7f20bb9028701a95b029699
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 93b0c5bcc7db818125c081c62db004e70b27552a
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 eb6c82c7d77b885f9579284add0a64495dece6c8
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 f2784997c266c29ef02884d4fc8c0580505af94a
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 cffde6c7d84ebd11090ddbde8b3c016cad1943dd
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 7cf66f9c7d1c20de1be37d9cee671a923ed11fdf
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 fab01f73f138e73ccf7ed755d05d6f9418379c39
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 e6fdfa0da3af862ad6c70708b1559b88ea8bfb70
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 3e4f3ac9368f1cdb3176cf656bf881e961fa67d5
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 8eda8fa69c0ce06c07f1f3c0ca3fccacbe915703
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 12e7e48fbed86c7047d5861aa084ca38617141fd
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 09457b88b3c9..627cf6a2db92 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -1473,16 +1473,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 ea2a3c2ab72cc77d7bf90e2ee90134f533794cf5
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 b65cf7da60cc7eb9815e094e704d475fe115c23e
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 388b45dfb943..09457b88b3c9 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -1471,19 +1471,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;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list