Rebased ref, commits from common ancestor:
commit 70da4f1d26cc7af2cd248b9b7e44420097c686b5
Author: Markus Mohrhard <markus.mohrh...@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 9a49cce9ffcf1f8756b69974658380744e58dfa5
Author: Markus Mohrhard <markus.mohrh...@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 4a6f559c6f61063605f4f32230a997146162cba5
Author: Markus Mohrhard <markus.mohrh...@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 019daab72104c2f66cd66a2ffaa03beb0d1a9f6c
Author: Markus Mohrhard <markus.mohrh...@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 f6e827f706d2a09ff4882a7a44e646fbfccd739c
Author: Markus Mohrhard <markus.mohrh...@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 aee268a2ccb485c536601be91d0b5c1feaa39d48
Author: Markus Mohrhard <markus.mohrh...@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 aee84a6fee90f25feb4fedebc759d45de3cdec24
Author: Markus Mohrhard <markus.mohrh...@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 934ddb1cf13906e53fec3b6b072f0e45622290a7
Author: Markus Mohrhard <markus.mohrh...@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 9e98a890eb09e099b81c30b72bd608f0668c2bba
Author: Markus Mohrhard <markus.mohrh...@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 5e8c3aab7acd24023d9f2569d9876e11e47e42b7
Author: Markus Mohrhard <markus.mohrh...@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 3f7ddb128a012ef6b9f5a21d7bbfa89614c190d6
Author: Markus Mohrhard <markus.mohrh...@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 24799406210d497f8d404448b8ab9af5972073f2
Author: Markus Mohrhard <markus.mohrh...@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 68ff6c820aca39b2b7cb2ad2822c1b9323fc408d
Author: Markus Mohrhard <markus.mohrh...@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 4015d903cf4021b7b4ab8406125de71eb97c8b44
Author: Markus Mohrhard <markus.mohrh...@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 7cd6d49d713a8909e515ee5d3aaff3a8175a2aeb
Author: Markus Mohrhard <markus.mohrh...@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 aad3f2a556adce6691f225a47d6c84711c721cf4
Author: Markus Mohrhard <markus.mohrh...@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 2967d5d34564060c51a42c044629e302f22d6338
Author: Markus Mohrhard <markus.mohrh...@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 562baa4b513f8773583a13f42910a2340312a08e
Author: Markus Mohrhard <markus.mohrh...@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 6a46ccf96f9952c547b27a27b52aec192ae056c6
Author: Markus Mohrhard <markus.mohrh...@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 65b01d427fb0ccff73bcc272ad2094fc89203cc3
Author: Markus Mohrhard <markus.mohrh...@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 1949ea1c6eb4b29121b18e42e3de28c490c96bea
Author: Markus Mohrhard <markus.mohrh...@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 3c2056665ff128c82f8efd3aeae1725b60de027c
Author: Markus Mohrhard <markus.mohrh...@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 588cef49ddd106ec19b1386b98c6932e36afa2b8
Author: Markus Mohrhard <markus.mohrh...@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 80a552e1b5e7f99cd5e512793ced76c774ed3e10
Author: Markus Mohrhard <markus.mohrh...@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 5339bb09a193770a34a188e12f5d5d8a4e9efcf3
Author: Markus Mohrhard <markus.mohrh...@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 cca48ff4c8f9945b4bf29ed559f7f84e5ab6074c
Author: Markus Mohrhard <markus.mohrh...@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 4b55b077aea4646ab1d5c832372ecfbd1cef411b
Author: Markus Mohrhard <markus.mohrh...@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 a77a29f768d4803ffddbef53682705e94b2e8000
Author: Markus Mohrhard <markus.mohrh...@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 6b74aec14c052c2c6c397d95038213267360a42b
Author: Markus Mohrhard <markus.mohrh...@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 <benja...@smedbergs.us>
+  2005-05-18 - Use the same CRC algorithm as bzip2, and leverage the CRC table
+               provided by libbz2.
+                 --Darin Fisher <da...@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 ac19b0cb7e3530904c140eeb4ab9a99d7aa083cc
Author: Markus Mohrhard <markus.mohrh...@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 694092fab99ad79a32d277ac58dfc3c7d07d8be7
Author: Markus Mohrhard <markus.mohrh...@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 ba4bb75c59e11d1b7733d11b8c768c852ef66201
Author: Markus Mohrhard <markus.mohrh...@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 75720325b1fb4ab93eeabed8acc19dbd30ddaf84
Author: Markus Mohrhard <markus.mohrh...@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 6c93b4693d17d648f33b6250c54ccf1434ff0c26
Author: Markus Mohrhard <markus.mohrh...@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;
-            osl::DirectoryItem::get(aPatchDirURL + "/update.info", aPatchInfo);
+            osl::DirectoryItem::get(Updater::getUpdateInfoURL(), aPatchInfo);
 
             if (aPatchInfo.is())
             {
-                OUString aInstallationDir( "$BRAND_BASE_DIR/");
-                rtl::Bootstrap::expandMacros(aInstallationDir);
-
                 osl::DirectoryItem aDirectoryItem;
-                osl::DirectoryItem::get(aInstallationDir + "/updated", 
aDirectoryItem);
+                osl::DirectoryItem::get(Updater::getUpdateDirURL(), 
aDirectoryItem);
                 bool bValidUpdateDirExists = aDirectoryItem.is();
                 if (bValidUpdateDirExists)
                 {
diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index e82e84f41bc6..a0e0e3bf4f6f 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -140,7 +140,7 @@ char** createCommandLine()
     }
     {
         // directory with the patch log

... etc. - the rest is truncated
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to