Rebased ref, commits from common ancestor: commit f722d61953c86f4b773b1b35d6a181950b493079 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 acb9e0ea14272563f65db54707e4f4a6fd154c61 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 e6770a4075e7..2ab197d96422 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 94d8f1a09f94e09180b2d703795e9b087e6b9b95 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 77ca56bd592fbf5fdd6067b7e9ff2586b70d079b 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 bbf8855787c4229170b0520fc42bc1d4ab8d2faa 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 85dd8dd39808..15c49b7eab02 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -1484,16 +1484,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 cc344723d676b9016a8cacbdd9aa00eeade93267 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 422d582fb097882eb2c1c21e2e43a7255c8bc5c1 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 f557848d17e2..85dd8dd39808 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -1482,19 +1482,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 - OUString aPatchDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/"); + OUString aPatchDir = Updater::getPatchDirURL(); rtl::Bootstrap::expandMacros(aPatchDir); OUString aTempDirPath = getPathFromURL(aPatchDir); createStr(aTempDirPath, pArgs, 1); @@ -152,9 +152,8 @@ char** createCommandLine() } { // the temporary updated build - OUString aPatchDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/update_dir/"); - rtl::Bootstrap::expandMacros(aPatchDir); - OUString aWorkingDir = getPathFromURL(aPatchDir); + OUString aUpdateDirURL = Updater::getUpdateDirURL(); + OUString aWorkingDir = getPathFromURL(aUpdateDirURL); createStr(aWorkingDir, pArgs, 3); } { @@ -162,15 +161,14 @@ char** createCommandLine() createStr(pPID, pArgs, 4); } { - OUString aExeDir( "$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/" ); + OUString aExeDir = Updater::getExecutableDirURL(); OUString aSofficePath = getPathFromURL(aExeDir); createStr(aSofficePath, pArgs, 5); } { // the executable to start after the successful update - OUString aSofficeDir( "$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/" ); - rtl::Bootstrap::expandMacros(aSofficeDir); - OUString aSofficePathURL = aSofficeDir + OUString::fromUtf8(pSofficeExeName); + OUString aExeDir = Updater::getExecutableDirURL(); + OUString aSofficePathURL = aExeDir + OUString::fromUtf8(pSofficeExeName); OUString aSofficePath = getPathFromURL(aSofficePathURL); createStr(aSofficePath, pArgs, 6); } @@ -564,4 +562,36 @@ void update_checker() } } +OUString Updater::getUpdateInfoURL() +{ + OUString aUpdateInfoURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/update.info"); + rtl::Bootstrap::expandMacros(aUpdateInfoURL); + + return aUpdateInfoURL; +} + +OUString Updater::getPatchDirURL() +{ + OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/"); + rtl::Bootstrap::expandMacros(aPatchDirURL); + + return aPatchDirURL; +} + +OUString Updater::getUpdateDirURL() +{ + OUString aUpdateDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/update_dir/"); + rtl::Bootstrap::expandMacros(aUpdateDirURL); + + return aUpdateDirURL; +} + +OUString Updater::getExecutableDirURL() +{ + OUString aExeDir( "$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/" ); + rtl::Bootstrap::expandMacros(aExeDir); + + return aExeDir; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/updater.hxx b/desktop/source/app/updater.hxx index fa5349afbe11..b36c1f91b306 100644 --- a/desktop/source/app/updater.hxx +++ b/desktop/source/app/updater.hxx @@ -16,6 +16,19 @@ void update(); void update_checker(); +class Updater +{ +private: + +public: + + static OUString getUpdateInfoURL(); + static OUString getPatchDirURL(); + static OUString getUpdateDirURL(); + static OUString getExecutableDirURL(); + +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit e7ac3e13cfb43105c5cb6eb7536426367e1d7442 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Apr 21 22:57:59 2017 +0200 either try to install an update or check for update Change-Id: Id1e879598ef34715786e10e163ed1e4689f3137a diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index c2055e20ce04..f557848d17e2 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -1501,8 +1501,7 @@ int Desktop::Main() update(); } } - - if (isTimeForUpdateCheck()) + else if (isTimeForUpdateCheck()) { sal_uInt64 nNow = tools::Time::GetSystemTicks(); std::shared_ptr< comphelper::ConfigurationChanges > batch( commit e96db7e3339b4d26f61703e3fa4e4e861ba66a22 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Apr 21 22:16:39 2017 +0200 normalize path for updater diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index 07f24b48378f..e82e84f41bc6 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -56,7 +56,31 @@ const char* pSofficeExeName = "soffice.exe"; OUString normalizePath(const OUString& rPath) { - return rPath.replaceAll("//", "/"); + OUString aPath = rPath.replaceAll("//", "/"); + + // remove final / + if (aPath.endsWith("/")) + { + aPath = aPath.copy(0, aPath.getLength() - 1); + } + + while (aPath.indexOf("/..") != -1) + { + sal_Int32 nIndex = aPath.indexOf("/.."); + sal_Int32 i = nIndex - 1; + for (; i > 0; --i) + { + if (aPath[i] == '/') + break; + } + + OUString aTempPath = aPath; + aPath = aTempPath.copy(0, i) + aPath.copy(nIndex + 3); + } + + SAL_DEBUG(aPath); + + return aPath; } void CopyFileToDir(const OUString& rTempDirURL, const OUString rFileName, const OUString& rOldDir) commit e965868ba3cf61c26673e8188b216abdbb3c6caa Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Apr 21 22:04:09 2017 +0200 better flexibility through configurable updated build directory Change-Id: Icaa814cdcd27171fbafc2407d55161cdc13e750e diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx index 18cf8b2cc966..57ac77507a8b 100644 --- a/onlineupdate/source/update/updater/updater.cxx +++ b/onlineupdate/source/update/updater/updater.cxx @@ -2357,8 +2357,8 @@ ProcessReplaceRequest() NS_T("%s/Contents"), gWorkingDirPath); #else - NS_T("%s.bak/updated"), - gInstallDirPath); + NS_T("%s"), + gWorkingDirPath); #endif // First try to remove the possibly existing temp directory, because if this commit c1ecda52bf74b5e5d5c0a1bfcea8662d095a8200 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Apr 21 21:14:50 2017 +0200 first stab at normalizing updater path Change-Id: I5ef2253068595c41577330395810b0797eff8cbb diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index f31f2800dc4b..07f24b48378f 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -54,6 +54,10 @@ const char* pSofficeExeName = "soffice.exe"; #error "Need implementation" #endif +OUString normalizePath(const OUString& rPath) +{ + return rPath.replaceAll("//", "/"); +} void CopyFileToDir(const OUString& rTempDirURL, const OUString rFileName, const OUString& rOldDir) { @@ -73,7 +77,7 @@ OUString getPathFromURL(const OUString& rURL) OUString aPath; osl::FileBase::getSystemPathFromFileURL(rURL, aPath); - return aPath; + return normalizePath(aPath); } void CopyUpdaterToTempDir(const OUString& rInstallDirURL, const OUString& rTempDirURL) commit 09171807bd2c0217dbf6eea6b40dd689fd1aef90 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Fri Apr 21 20:50:21 2017 +0200 use an update dir that is in the user profile The user profile should always be writable Change-Id: I45f7e05e128d62a5930e6db9793b8cf4e7751046 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index a700527a43b9..f31f2800dc4b 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -111,17 +111,22 @@ char** createCommandLine() createStr(pUpdaterName, pArgs, 0); } { + // directory with the patch log OUString aPatchDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/"); rtl::Bootstrap::expandMacros(aPatchDir); OUString aTempDirPath = getPathFromURL(aPatchDir); createStr(aTempDirPath, pArgs, 1); } { + // the actual update directory OUString aInstallPath = getPathFromURL(aLibExecDirURL); createStr(aInstallPath, pArgs, 2); } { - OUString aWorkingDir = getPathFromURL(aLibExecDirURL + "/updated"); + // the temporary updated build + OUString aPatchDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/update_dir/"); + rtl::Bootstrap::expandMacros(aPatchDir); + OUString aWorkingDir = getPathFromURL(aPatchDir); createStr(aWorkingDir, pArgs, 3); } { @@ -134,6 +139,7 @@ char** createCommandLine() createStr(aSofficePath, pArgs, 5); } { + // the executable to start after the successful update OUString aSofficeDir( "$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/" ); rtl::Bootstrap::expandMacros(aSofficeDir); OUString aSofficePathURL = aSofficeDir + OUString::fromUtf8(pSofficeExeName); @@ -202,7 +208,9 @@ void CreateValidUpdateDir(const update_info& update_info) OUString aInstallDir("$BRAND_BASE_DIR"); rtl::Bootstrap::expandMacros(aInstallDir); OUString aInstallPath = getPathFromURL(aInstallDir); - OUString aWorkdirPath = getPathFromURL(aInstallDir + "/updated"); + OUString aUpdatedBuildDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/update_dir/"); + rtl::Bootstrap::expandMacros(aUpdatedBuildDir); + OUString aWorkdirPath = getPathFromURL(aUpdatedBuildDir); OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/"); rtl::Bootstrap::expandMacros(aPatchDirURL); commit a9e833741b723990a02e91379f7496726ea53b3d Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Wed Apr 19 13:28:02 2017 +0200 don't crash when we get bad response Change-Id: I4bc68e9f9604a8a39f36f10434571cd9fbb48ae1 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index b6abf4c01b74..a700527a43b9 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -522,6 +522,10 @@ void update_checker() { SAL_WARN("desktop.updater", "error during the update check"); } + catch (...) + { + SAL_WARN("desktop.updater", "unknown error during the update check"); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 28cca11b5a8dcb7194976a741b9c57d6b34a9f19 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Wed Apr 19 13:20:47 2017 +0200 ignore SIGPIPE in glx test process Change-Id: I31977f86290b4fd7e0869af85f5132ae7cd9d5fd diff --git a/vcl/unx/glxtest.cxx b/vcl/unx/glxtest.cxx index efe55910d164..383be628dfa9 100644 --- a/vcl/unx/glxtest.cxx +++ b/vcl/unx/glxtest.cxx @@ -25,6 +25,7 @@ #include <fcntl.h> #include "stdint.h" #include <string.h> +#include <signal.h> #include "opengl/x11/glxtest.hxx" @@ -98,6 +99,7 @@ x_error_handler(Display *, XErrorEvent *ev) void glxtest() { + signal(SIGPIPE, SIG_IGN); // we want to redirect to /dev/null stdout, stderr, and while we're at it, // any PR logging file descriptors. To that effect, we redirect all positive // file descriptors up to what open() returns here. In particular, 1 is stdout and 2 is stderr. commit 548bf97599690b44905fa622a2cf950a26bb9c39 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 18 19:42:53 2017 +0200 hard coding the number of entries just leads to problems Change-Id: I527c2c881bf46b1724b8da9223b2614ff30fbec7 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index e9d989acc26b..b6abf4c01b74 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -323,12 +323,6 @@ update_info parse_response(const std::string& rResponse) throw invalid_update_info(); } - if (aRootKeys.size() != 5) - { - SAL_WARN("desktop.Update", "invalid root entries: " << rResponse); - throw invalid_update_info(); - } - orcus::json::detail::node aFromNode = aDocumentRoot.child("from"); if (aFromNode.type() != orcus::json_node_t::string) { commit 9059f67e77215c3e98bfa762ea9a019b7dd9c07a Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 18 19:16:02 2017 +0200 version entry is no more Change-Id: I5011deec4a3b00b22d68d5dff594586d74d717ba diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index dffafcbcde53..e9d989acc26b 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -162,7 +162,6 @@ struct update_info { OUString aFromBuildID; OUString aSeeAlsoURL; - OUString aNewVersion; update_file aUpdateFile; std::vector<language_file> aLanguageFiles; @@ -342,12 +341,6 @@ update_info parse_response(const std::string& rResponse) throw invalid_update_info(); } - orcus::json::detail::node aVersionNode = aDocumentRoot.child("version"); - if (aVersionNode.type() != orcus::json_node_t::string) - { - throw invalid_update_info(); - } - orcus::json::detail::node aUpdateNode = aDocumentRoot.child("update"); if (aUpdateNode.type() != orcus::json_node_t::object) { @@ -362,7 +355,6 @@ update_info parse_response(const std::string& rResponse) update_info aUpdateInfo; aUpdateInfo.aFromBuildID = toOUString(aFromNode.string_value().str()); - aUpdateInfo.aNewVersion = toOUString(aVersionNode.string_value().str()); aUpdateInfo.aSeeAlsoURL = toOUString(aSeeAlsoNode.string_value().str()); aUpdateInfo.aUpdateFile = parse_update_file(aUpdateNode); commit 44623acd158fcbd30ab8d99418fe7e0ba8b01ccf Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 18 13:30:46 2017 +0200 protect the downloading of the update info also with try..catch Change-Id: Ie3f2687670b02d8af85016c25b49cb42517701b9 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index a4bf6d6e9d81..dffafcbcde53 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -517,10 +517,10 @@ void update_checker() "/" + aBuildID + "/" + aBuildTarget + "/" + "/" + aChannel; OString aURL = OUStringToOString(aDownloadCheckURL, RTL_TEXTENCODING_UTF8); - std::string response_body = download_content(aURL, false); try { + std::string response_body = download_content(aURL, false); if (!response_body.empty()) { update_info aUpdateInfo = parse_response(response_body); commit 7229e8bc24dfd7f7f4ebdce703562861a2aeebef Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 18 13:08:40 2017 +0200 update the update URL and adapt to the server changes Change-Id: I6ece7924e6e0980c2bb4fffa9d733e6352382084 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index 2b9c68a0d969..a4bf6d6e9d81 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -509,15 +509,12 @@ void update_checker() OUString aProductName = utl::ConfigManager::getProductName(); OUString aBuildID("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ":buildid}"); rtl::Bootstrap::expandMacros(aBuildID); - OUString aVersion = "5.3.0.0.alpha0+"; OUString aBuildTarget = "${_OS}_${_ARCH}"; rtl::Bootstrap::expandMacros(aBuildTarget); - OUString aLocale = "en-US"; OUString aChannel = officecfg::Office::Update::Update::UpdateChannel::get(); - OUString aDownloadCheckURL = aDownloadCheckBaseURL + "update/1/" + aProductName + - "/" + aVersion + "/" + aBuildID + "/" + aBuildTarget + "/" + aLocale + - "/" + aChannel; + OUString aDownloadCheckURL = aDownloadCheckBaseURL + "update/check/1/" + aProductName + + "/" + aBuildID + "/" + aBuildTarget + "/" + "/" + aChannel; OString aURL = OUStringToOString(aDownloadCheckURL, RTL_TEXTENCODING_UTF8); std::string response_body = download_content(aURL, false); commit 3e87d6b0a07774cb24abf097924d7b9eae8a3255 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 25 00:50:14 2017 +0200 send the csrf token with the updater scripts Change-Id: Iad6953b8206ba02ca09069115e168230b27f72fe diff --git a/bin/update/upload_build_config.py b/bin/update/upload_build_config.py index 0380cc1c323b..3267f021b8e3 100755 --- a/bin/update/upload_build_config.py +++ b/bin/update/upload_build_config.py @@ -29,9 +29,11 @@ def main(argv): r1 = session.post(login_url, data=login_data, headers={"Referer": login_url}) url = base_address + "update/upload/release" + data = {} + data['csrfmiddlewaretoken'] = csrftoken build_config = os.path.join(sys.argv[1], "build_config.json") - r = session.post(url, files={'release_config': open(build_config, "r")}) + r = session.post(url, files={'release_config': open(build_config, "r")}, data=data) print(r.content) if r.status_code != 200: sys.exit(1) commit b716534c8124011f68dafd6b5bdb8653505d2db1 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 25 00:49:25 2017 +0200 use the path and not the URL string Change-Id: I045e801a86f656a182bd1c5c42aca29cde694f71 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index 8c71f3bc2c9c..2b9c68a0d969 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -114,7 +114,7 @@ char** createCommandLine() OUString aPatchDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/"); rtl::Bootstrap::expandMacros(aPatchDir); OUString aTempDirPath = getPathFromURL(aPatchDir); - createStr(aPatchDir, pArgs, 1); + createStr(aTempDirPath, pArgs, 1); } { OUString aInstallPath = getPathFromURL(aLibExecDirURL); commit 7614d87ff50129796183d2f072067dd9b959c452 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 25 00:48:39 2017 +0200 use consistent method names Change-Id: I19e066b7e4c4ba1fc1b0802e80260a6d9b0d9b9a diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index 2f5cb9660dfd..c2055e20ce04 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -1498,7 +1498,7 @@ int Desktop::Main() bool bValidUpdateDirExists = aDirectoryItem.is(); if (bValidUpdateDirExists) { - Update(); + update(); } } diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index 83d2a3010bf6..8c71f3bc2c9c 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -170,7 +170,7 @@ struct update_info } -void Update() +void update() { OUString aLibExecDirURL( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER ); rtl::Bootstrap::expandMacros(aLibExecDirURL); diff --git a/desktop/source/app/updater.hxx b/desktop/source/app/updater.hxx index fab760516952..fa5349afbe11 100644 --- a/desktop/source/app/updater.hxx +++ b/desktop/source/app/updater.hxx @@ -12,7 +12,7 @@ #include <rtl/ustring.hxx> -void Update(); +void update(); void update_checker(); commit 7b309f403d7a9b3ef9782ad45b7b5c9bf89efda0 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 25 00:46:51 2017 +0200 follow redirects when downloading update files Change-Id: Ic6679aa3d150499b354ccb396c136178d662bb67 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index 5b4b5c1ebac3..83d2a3010bf6 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -402,6 +402,7 @@ std::string download_content(const OString& rURL, bool bFile) curl_slist* headerlist = nullptr; headerlist = curl_slist_append(headerlist, buf); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); // follow redirects std::string response_body; utl::TempFile aTempFile; commit 0314e47b56b31adb9a97111648a192d0183ecb97 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Apr 25 00:45:27 2017 +0200 executable names on linux and windows are different Also use different user agent strings. Change-Id: I047e743f2ea13ee5ea6bff1cb5d6d86ca2ac6417 diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx index 0ca03bc9de9e..5b4b5c1ebac3 100644 --- a/desktop/source/app/updater.cxx +++ b/desktop/source/app/updater.cxx @@ -38,17 +38,22 @@ class error_updater : public std::exception { }; -static const char kUserAgent[] = "UpdateChecker/1.0 (Linux)"; +#ifdef UNX +static const char kUserAgent[] = "LibreOffice UpdateChecker/1.0 (Linux)"; +#else +static const char kUserAgent[] = "LibreOffice UpdateChecker/1.0 (unknown platform)"; +#endif #ifdef UNX const char* pUpdaterName = "updater"; +const char* pSofficeExeName = "soffice"; #elif defined(WNT) const char* pUpdaterName = "updater.exe"; +const char* pSofficeExeName = "soffice.exe"; #else #error "Need implementation" #endif -const char* pSofficeExeName = "soffice"; void CopyFileToDir(const OUString& rTempDirURL, const OUString rFileName, const OUString& rOldDir) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits