summaryrefslogtreecommitdiff
path: root/onlineupdate/source/update/updater
diff options
context:
space:
mode:
Diffstat (limited to 'onlineupdate/source/update/updater')
-rw-r--r--onlineupdate/source/update/updater/Makefile.in28
-rw-r--r--onlineupdate/source/update/updater/archivereader.cxx349
-rw-r--r--onlineupdate/source/update/updater/archivereader.h39
-rw-r--r--onlineupdate/source/update/updater/bspatch.cxx198
-rwxr-xr-xonlineupdate/source/update/updater/gen_cert_header.py42
-rw-r--r--onlineupdate/source/update/updater/launchchild_osx.mm138
-rw-r--r--onlineupdate/source/update/updater/loaddlls.cxx119
-rw-r--r--onlineupdate/source/update/updater/macbuild/Contents/Info.plist35
-rw-r--r--onlineupdate/source/update/updater/macbuild/Contents/PkgInfo1
-rw-r--r--onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in7
-rw-r--r--onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib19
-rw-r--r--onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib22
-rw-r--r--onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nibbin5567 -> 0 bytes
-rw-r--r--onlineupdate/source/update/updater/macbuild/Contents/Resources/updater.icnsbin55969 -> 0 bytes
-rw-r--r--onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx52
-rw-r--r--onlineupdate/source/update/updater/progressui-unused/progressui_osx.mm141
-rw-r--r--onlineupdate/source/update/updater/progressui.h36
-rw-r--r--onlineupdate/source/update/updater/progressui_gtk.cxx147
-rw-r--r--onlineupdate/source/update/updater/progressui_gtk_icon.h205
-rw-r--r--onlineupdate/source/update/updater/progressui_null.cxx27
-rw-r--r--onlineupdate/source/update/updater/progressui_win.cxx348
-rw-r--r--onlineupdate/source/update/updater/resource.h29
-rw-r--r--onlineupdate/source/update/updater/updater-common.build119
-rw-r--r--onlineupdate/source/update/updater/updater-xpcshell/Makefile.in32
-rw-r--r--onlineupdate/source/update/updater/updater-xpcshell/moz.build13
-rw-r--r--onlineupdate/source/update/updater/updater.cxx4594
-rw-r--r--onlineupdate/source/update/updater/updater.exe.comctl32.manifest38
-rw-r--r--onlineupdate/source/update/updater/updater.exe.manifest26
-rw-r--r--onlineupdate/source/update/updater/updater.icobin2238 -> 0 bytes
-rw-r--r--onlineupdate/source/update/updater/updater.pngbin2181 -> 0 bytes
-rw-r--r--onlineupdate/source/update/updater/updater.rc137
-rw-r--r--onlineupdate/source/update/updater/updater.svg1
-rw-r--r--onlineupdate/source/update/updater/win_dirent.cxx89
-rw-r--r--onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx429
-rw-r--r--onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h174
35 files changed, 0 insertions, 7634 deletions
diff --git a/onlineupdate/source/update/updater/Makefile.in b/onlineupdate/source/update/updater/Makefile.in
deleted file mode 100644
index 57813b36a20c..000000000000
--- a/onlineupdate/source/update/updater/Makefile.in
+++ /dev/null
@@ -1,28 +0,0 @@
-# vim:set ts=8 sw=8 sts=8 noet:
-# 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/.
-
-# For changes here, also consider ./updater-xpcshell/Makefile.in
-
-# This is how the xpcshellCertificate.der file is generated, in case we ever
-# have to regenerate it.
-# ./certutil -L -d modules/libmar/tests/unit/data -n mycert -r > xpcshellCertificate.der
-xpcshellCert.h: xpcshellCertificate.der
-
-ifdef MOZ_WIDGET_GTK
-libs:: updater.png
- $(NSINSTALL) -D $(DIST)/bin/icons
- $(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/icons
-endif
-
-ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
-libs::
- $(NSINSTALL) -D $(DIST)/bin/updater.app
- rsync -a -C --exclude '*.in' $(srcdir)/macbuild/Contents $(DIST)/bin/updater.app
- sed -e 's/%APP_NAME%/$(MOZ_APP_DISPLAYNAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | \
- iconv -f UTF-8 -t UTF-16 > $(DIST)/bin/updater.app/Contents/Resources/English.lproj/InfoPlist.strings
- $(NSINSTALL) -D $(DIST)/bin/updater.app/Contents/MacOS
- $(NSINSTALL) $(DIST)/bin/updater $(DIST)/bin/updater.app/Contents/MacOS
- rm -f $(DIST)/bin/updater
-endif
diff --git a/onlineupdate/source/update/updater/archivereader.cxx b/onlineupdate/source/update/updater/archivereader.cxx
deleted file mode 100644
index d669211437e9..000000000000
--- a/onlineupdate/source/update/updater/archivereader.cxx
+++ /dev/null
@@ -1,349 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include "bzlib.h"
-#include "archivereader.h"
-#include "errors.h"
-#ifdef _WIN32
-#include "updatehelper.h"
-#endif
-
-// These are generated at compile time based on the DER file for the channel
-// being used
-#ifdef VERIFY_MAR_SIGNATURE
-#ifdef TEST_UPDATER
-#include "../xpcshellCert.h"
-#else
-#include "onlineupdate/primaryCert.h"
-#include "onlineupdate/secondaryCert.h"
-#endif
-#endif
-
-#if defined(_WIN32)
-#define UPDATER_NO_STRING_GLUE_STL
-#endif
-#include "nsVersionComparator.h"
-#undef UPDATER_NO_STRING_GLUE_STL
-
-#if defined(UNIX)
-# include <sys/types.h>
-#elif defined(_WIN32)
-# include <io.h>
-#endif
-
-static int inbuf_size = 262144;
-static int outbuf_size = 262144;
-static char *inbuf = nullptr;
-static char *outbuf = nullptr;
-
-/**
- * Performs a verification on the opened MAR file with the passed in
- * certificate name ID and type ID.
- *
- * @param archive The MAR file to verify the signature on.
- * @param certData The certificate data.
- * @return OK on success, CERT_VERIFY_ERROR on failure.
-*/
-template<uint32_t SIZE>
-int
-VerifyLoadedCert(MarFile *archive, const uint8_t (&certData)[SIZE])
-{
- (void)archive;
- (void)certData;
-
-#ifdef VERIFY_MAR_SIGNATURE
- const uint32_t size = SIZE;
- const uint8_t* const data = &certData[0];
- if (mar_verify_signatures(archive, &data, &size, 1))
- {
- return CERT_VERIFY_ERROR;
- }
-#endif
-
- return OK;
-}
-
-/**
- * Performs a verification on the opened MAR file. Both the primary and backup
- * keys stored are stored in the current process and at least the primary key
- * will be tried. Success will be returned as long as one of the two
- * signatures verify.
- *
- * @return OK on success
-*/
-int
-ArchiveReader::VerifySignature()
-{
- if (!mArchive)
- {
- return ARCHIVE_NOT_OPEN;
- }
-
-#ifndef VERIFY_MAR_SIGNATURE
- return OK;
-#else
-#ifdef TEST_UPDATER
- int rv = VerifyLoadedCert(mArchive, xpcshellCertData);
-#else
- int rv = VerifyLoadedCert(mArchive, primaryCertData);
- if (rv != OK)
- {
- rv = VerifyLoadedCert(mArchive, secondaryCertData);
- }
-#endif
- return rv;
-#endif
-}
-
-/**
- * Verifies that the MAR file matches the current product, channel, and version
- *
- * @param MARChannelID The MAR channel name to use, only updates from MARs
- * with a matching MAR channel name will succeed.
- * If an empty string is passed, no check will be done
- * for the channel name in the product information block.
- * If a comma separated list of values is passed then
- * one value must match.
- * @param appVersion The application version to use, only MARs with an
- * application version >= to appVersion will be applied.
- * @return OK on success
- * COULD_NOT_READ_PRODUCT_INFO_BLOCK if the product info block
- * could not be read.
- * MARCHANNEL_MISMATCH_ERROR if update-settings.ini's MAR
- * channel ID doesn't match the MAR
- * file's MAR channel ID.
- * VERSION_DOWNGRADE_ERROR if the application version for
- * this updater is newer than the
- * one in the MAR.
- */
-int
-ArchiveReader::VerifyProductInformation(const char *MARChannelID,
- const char *appVersion)
-{
- if (!mArchive)
- {
- return ARCHIVE_NOT_OPEN;
- }
-
- ProductInformationBlock productInfoBlock;
- int rv = mar_read_product_info_block(mArchive,
- &productInfoBlock);
- if (rv != OK)
- {
- return COULD_NOT_READ_PRODUCT_INFO_BLOCK_ERROR;
- }
-
- // Only check the MAR channel name if specified, it should be passed in from
- // the update-settings.ini file.
- if (MARChannelID && strlen(MARChannelID))
- {
- // Check for at least one match in the comma separated list of values.
- const char *delimiter = " ,\t";
- // Make a copy of the string in case a read only memory buffer
- // was specified. strtok modifies the input buffer.
- char channelCopy[512] = { 0 };
- strncpy(channelCopy, MARChannelID, sizeof(channelCopy) - 1);
- char *channel = strtok(channelCopy, delimiter);
- rv = MAR_CHANNEL_MISMATCH_ERROR;
- while (channel)
- {
- if (!strcmp(channel, productInfoBlock.MARChannelID))
- {
- rv = OK;
- break;
- }
- channel = strtok(nullptr, delimiter);
- }
- }
-
- if (rv == OK)
- {
- /* Compare both versions to ensure we don't have a downgrade
- -1 if appVersion is older than productInfoBlock.productVersion
- 1 if appVersion is newer than productInfoBlock.productVersion
- 0 if appVersion is the same as productInfoBlock.productVersion
- This even works with strings like:
- - 12.0a1 being older than 12.0a2
- - 12.0a2 being older than 12.0b1
- - 12.0a1 being older than 12.0
- - 12.0 being older than 12.1a1 */
- int versionCompareResult =
- mozilla::CompareVersions(appVersion, productInfoBlock.productVersion);
- if (1 == versionCompareResult)
- {
- rv = VERSION_DOWNGRADE_ERROR;
- }
- }
-
- free((void *)productInfoBlock.MARChannelID);
- free((void *)productInfoBlock.productVersion);
- return rv;
-}
-
-int
-ArchiveReader::Open(const NS_tchar *path)
-{
- if (mArchive)
- Close();
-
- if (!inbuf)
- {
- inbuf = (char *)malloc(inbuf_size);
- if (!inbuf)
- {
- // Try again with a smaller buffer.
- inbuf_size = 1024;
- inbuf = (char *)malloc(inbuf_size);
- if (!inbuf)
- return ARCHIVE_READER_MEM_ERROR;
- }
- }
-
- if (!outbuf)
- {
- outbuf = (char *)malloc(outbuf_size);
- if (!outbuf)
- {
- // Try again with a smaller buffer.
- outbuf_size = 1024;
- outbuf = (char *)malloc(outbuf_size);
- if (!outbuf)
- return ARCHIVE_READER_MEM_ERROR;
- }
- }
-
-#ifdef _WIN32
- mArchive = mar_wopen(path);
-#else
- mArchive = mar_open(path);
-#endif
- if (!mArchive)
- return READ_ERROR;
-
- return OK;
-}
-
-void
-ArchiveReader::Close()
-{
- if (mArchive)
- {
- mar_close(mArchive);
- mArchive = nullptr;
- }
-
- if (inbuf)
- {
- free(inbuf);
- inbuf = nullptr;
- }
-
- if (outbuf)
- {
- free(outbuf);
- outbuf = nullptr;
- }
-}
-
-int
-ArchiveReader::ExtractFile(const char *name, const NS_tchar *dest)
-{
- const MarItem *item = mar_find_item(mArchive, name);
- if (!item)
- return READ_ERROR;
-
-#ifdef _WIN32
- FILE* fp = _wfopen(dest, L"wb+");
-#else
- int fd = creat(dest, item->flags);
- if (fd == -1)
- return WRITE_ERROR;
-
- FILE *fp = fdopen(fd, "wb");
-#endif
- if (!fp)
- return WRITE_ERROR;
-
- int rv = ExtractItemToStream(item, fp);
-
- fclose(fp);
- return rv;
-}
-
-int
-ArchiveReader::ExtractFileToStream(const char *name, FILE *fp)
-{
- const MarItem *item = mar_find_item(mArchive, name);
- if (!item)
- return READ_ERROR;
-
- return ExtractItemToStream(item, fp);
-}
-
-int
-ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp)
-{
- /* decompress the data chunk by chunk */
-
- bz_stream strm;
- int offset, inlen, ret = OK;
-
- memset(&strm, 0, sizeof(strm));
- if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK)
- return UNEXPECTED_BZIP_ERROR;
-
- offset = 0;
- for (;;)
- {
- if (!item->length)
- {
- ret = UNEXPECTED_MAR_ERROR;
- break;
- }
-
- if (offset < (int) item->length && strm.avail_in == 0)
- {
- inlen = mar_read(mArchive, item, offset, inbuf, inbuf_size);
- if (inlen <= 0)
- return READ_ERROR;
- offset += inlen;
- strm.next_in = inbuf;
- strm.avail_in = inlen;
- }
-
- strm.next_out = outbuf;
- strm.avail_out = outbuf_size;
-
- ret = BZ2_bzDecompress(&strm);
- if (ret != BZ_OK && ret != BZ_STREAM_END)
- {
- ret = UNEXPECTED_BZIP_ERROR;
- break;
- }
-
- int outlen = outbuf_size - strm.avail_out;
- if (outlen)
- {
- if (fwrite(outbuf, outlen, 1, fp) != 1)
- {
- ret = WRITE_ERROR_EXTRACT;
- break;
- }
- }
-
- if (ret == BZ_STREAM_END)
- {
- ret = OK;
- break;
- }
- }
-
- BZ2_bzDecompressEnd(&strm);
- return ret;
-}
diff --git a/onlineupdate/source/update/updater/archivereader.h b/onlineupdate/source/update/updater/archivereader.h
deleted file mode 100644
index 090b787f9cf5..000000000000
--- a/onlineupdate/source/update/updater/archivereader.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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 ArchiveReader_h__
-#define ArchiveReader_h__
-
-#include <stdio.h>
-#include <onlineupdate/mar.h>
-#include "types.hxx"
-
-// This class provides an API to extract files from an update archive.
-class ArchiveReader
-{
-public:
- ArchiveReader() : mArchive(nullptr) {}
- ~ArchiveReader()
- {
- Close();
- }
-
- int Open(const NS_tchar *path);
- int VerifySignature();
- int VerifyProductInformation(const char *MARChannelID,
- const char *appVersion);
- void Close();
-
- int ExtractFile(const char *item, const NS_tchar *destination);
- int ExtractFileToStream(const char *item, FILE *fp);
-
-private:
- int ExtractItemToStream(const MarItem *item, FILE *fp);
-
- MarFile *mArchive;
-};
-
-#endif // ArchiveReader_h__
diff --git a/onlineupdate/source/update/updater/bspatch.cxx b/onlineupdate/source/update/updater/bspatch.cxx
deleted file mode 100644
index 219c4d74cafa..000000000000
--- a/onlineupdate/source/update/updater/bspatch.cxx
+++ /dev/null
@@ -1,198 +0,0 @@
-/*-
- * Copyright 2003,2004 Colin Percival
- * All rights reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Changelog:
- * 2005-04-26 - Define the header as a C structure, add a CRC32 checksum to
- * the header, and make all the types 32-bit.
- * --Benjamin Smedberg <benjamin@smedbergs.us>
- */
-
-#include "bspatch.h"
-#include "errors.h"
-
-#include <algorithm>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <limits.h>
-
-#if defined(_WIN32)
-# include <io.h>
-#else
-# include <unistd.h>
-#endif
-
-#ifdef _WIN32
-# include <winsock2.h>
-#else
-# include <arpa/inet.h>
-#endif
-
-#ifndef SSIZE_MAX
-# define SSIZE_MAX LONG_MAX
-#endif
-
-int
-MBS_ReadHeader(FILE* file, MBSPatchHeader *header)
-{
- size_t s = fread(header, 1, sizeof(MBSPatchHeader), file);
- if (s != sizeof(MBSPatchHeader))
- return READ_ERROR;
-
- header->slen = ntohl(header->slen);
- header->scrc32 = ntohl(header->scrc32);
- header->dlen = ntohl(header->dlen);
- header->cblen = ntohl(header->cblen);
- header->difflen = ntohl(header->difflen);
- header->extralen = ntohl(header->extralen);
-
- struct stat hs;
- s = fstat(fileno(file), &hs);
- if (s)
- return READ_ERROR;
-
- if (memcmp(header->tag, "MBDIFF10", 8) != 0)
- return UNEXPECTED_BSPATCH_ERROR;
-
- if (sizeof(MBSPatchHeader) +
- header->cblen +
- header->difflen +
- header->extralen != uint32_t(hs.st_size))
- return UNEXPECTED_BSPATCH_ERROR;
-
- return OK;
-}
-
-int
-MBS_ApplyPatch(const MBSPatchHeader *header, FILE* patchFile,
- unsigned char *fbuffer, FILE* file)
-{
- unsigned char *fbufend = fbuffer + header->slen;
-
- unsigned char *buf = (unsigned char*) malloc(header->cblen +
- header->difflen +
- header->extralen);
- if (!buf)
- return BSPATCH_MEM_ERROR;
-
- int rv = OK;
-
- size_t r = header->cblen + header->difflen + header->extralen;
- unsigned char *wb = buf;
- while (r)
- {
- const size_t count = std::min(r, size_t(SSIZE_MAX));
- size_t c = fread(wb, 1, count, patchFile);
- if (c != count)
- {
- rv = READ_ERROR;
- goto end;
- }
-
- r -= c;
- wb += c;
- }
-
- {
- MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf;
- unsigned char *diffsrc = buf + header->cblen;
- unsigned char *extrasrc = diffsrc + header->difflen;
-
- MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc;
- unsigned char *diffend = extrasrc;
- unsigned char *extraend = extrasrc + header->extralen;
-
- do
- {
- ctrlsrc->x = ntohl(ctrlsrc->x);
- ctrlsrc->y = ntohl(ctrlsrc->y);
- ctrlsrc->z = ntohl(ctrlsrc->z);
-
-#ifdef DEBUG_bsmedberg
- printf("Applying block:\n"
- " x: %u\n"
- " y: %u\n"
- " z: %i\n",
- ctrlsrc->x,
- ctrlsrc->y,
- ctrlsrc->z);
-#endif
-
- /* Add x bytes from oldfile to x bytes from the diff block */
-
- if (fbuffer + ctrlsrc->x > fbufend ||
- diffsrc + ctrlsrc->x > diffend)
- {
- rv = UNEXPECTED_BSPATCH_ERROR;
- goto end;
- }
- for (uint32_t i = 0; i < ctrlsrc->x; ++i)
- {
- diffsrc[i] += fbuffer[i];
- }
- if ((uint32_t) fwrite(diffsrc, 1, ctrlsrc->x, file) != ctrlsrc->x)
- {
- rv = WRITE_ERROR_PATCH_FILE;
- goto end;
- }
- fbuffer += ctrlsrc->x;
- diffsrc += ctrlsrc->x;
-
- /* Copy y bytes from the extra block */
-
- if (extrasrc + ctrlsrc->y > extraend)
- {
- rv = UNEXPECTED_BSPATCH_ERROR;
- goto end;
- }
- if ((uint32_t) fwrite(extrasrc, 1, ctrlsrc->y, file) != ctrlsrc->y)
- {
- rv = WRITE_ERROR_PATCH_FILE;
- goto end;
- }
- extrasrc += ctrlsrc->y;
-
- /* "seek" forwards in oldfile by z bytes */
-
- if (fbuffer + ctrlsrc->z > fbufend)
- {
- rv = UNEXPECTED_BSPATCH_ERROR;
- goto end;
- }
- fbuffer += ctrlsrc->z;
-
- /* and on to the next control block */
-
- ++ctrlsrc;
- }
- while (ctrlsrc < ctrlend);
- }
-
-end:
- free(buf);
- return rv;
-}
diff --git a/onlineupdate/source/update/updater/gen_cert_header.py b/onlineupdate/source/update/updater/gen_cert_header.py
deleted file mode 100755
index 3f3798cfb425..000000000000
--- a/onlineupdate/source/update/updater/gen_cert_header.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-import os
-import sys
-import binascii
-
-try:
- from configparser import ConfigParser
-except ImportError:
- from ConfigParser import SafeConfigParser as ConfigParser
-
-def file_byte_generator(filename):
- with open(filename, "rb") as f:
- block = f.read()
- return block
-
-def eprint(*args, **kwargs):
- print(*args, file=sys.stderr, **kwargs)
-
-def create_header(array_name, in_filename):
- if sys.version_info >= (3,0):
- hexified = ["0x" + binascii.hexlify(bytes([inp])).decode('ascii') for inp in file_byte_generator(in_filename)]
- else:
- hexified = ["0x" + binascii.hexlify(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:
- eprint('ERROR: usage: gen_cert_header.py array_name update_config_file')
- sys.exit(1)
-
- if not os.path.exists(sys.argv[2]):
- eprint('The config file %s does not exist'%(sys.argv[2]))
- sys.exit(1)
-
- config = ConfigParser()
- config.read(sys.argv[2])
- sys.exit(create_header(sys.argv[1], config.get('Updater', 'certificate-der')))
diff --git a/onlineupdate/source/update/updater/launchchild_osx.mm b/onlineupdate/source/update/updater/launchchild_osx.mm
deleted file mode 100644
index 9e4e08d372fe..000000000000
--- a/onlineupdate/source/update/updater/launchchild_osx.mm
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#include <Cocoa/Cocoa.h>
-#include <CoreServices/CoreServices.h>
-#include <crt_externs.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <spawn.h>
-#include "readstrings.h"
-
-// Prefer the currently running architecture (this is the same as the
-// architecture that launched the updater) and fallback to CPU_TYPE_ANY if it
-// is no longer available after the update.
-static cpu_type_t pref_cpu_types[2] = {
-#if defined(__i386__)
- CPU_TYPE_X86,
-#elif defined(__x86_64__)
- CPU_TYPE_X86_64,
-#elif defined(__ppc__)
- CPU_TYPE_POWERPC,
-#endif
- CPU_TYPE_ANY };
-
-void LaunchChild(int argc, char **argv)
-{
- // Initialize spawn attributes.
- posix_spawnattr_t spawnattr;
- if (posix_spawnattr_init(&spawnattr) != 0) {
- printf("Failed to init posix spawn attribute.");
- return;
- }
-
- // Set spawn attributes.
- size_t attr_count = 2;
- size_t attr_ocount = 0;
- if (posix_spawnattr_setbinpref_np(&spawnattr, attr_count, pref_cpu_types, &attr_ocount) != 0 ||
- attr_ocount != attr_count) {
- printf("Failed to set binary preference on posix spawn attribute.");
- posix_spawnattr_destroy(&spawnattr);
- return;
- }
-
- // "posix_spawnp" uses null termination for arguments rather than a count.
- // Note that we are not duplicating the argument strings themselves.
- char** argv_copy = (char**)malloc((argc + 1) * sizeof(char*));
- if (!argv_copy) {
- printf("Failed to allocate memory for arguments.");
- posix_spawnattr_destroy(&spawnattr);
- return;
- }
- for (int i = 0; i < argc; i++) {
- argv_copy[i] = argv[i];
- }
- argv_copy[argc] = NULL;
-
- // Pass along our environment.
- char** envp = NULL;
- char*** cocoaEnvironment = _NSGetEnviron();
- if (cocoaEnvironment) {
- envp = *cocoaEnvironment;
- }
-
- int result = posix_spawnp(NULL, argv_copy[0], NULL, &spawnattr, argv_copy, envp);
-
- free(argv_copy);
- posix_spawnattr_destroy(&spawnattr);
-
- if (result != 0) {
- printf("Process spawn failed with code %d!", result);
- }
-}
-
-void
-LaunchMacPostProcess(const char* aAppBundle)
-{
- // Launch helper to perform post processing for the update; this is the Mac
- // analogue of LaunchWinPostProcess (PostUpdateWin).
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSString* iniPath = [NSString stringWithUTF8String:aAppBundle];
- iniPath =
- [iniPath stringByAppendingPathComponent:@"Contents/Resources/updater.ini"];
-
- NSFileManager* fileManager = [NSFileManager defaultManager];
- if (![fileManager fileExistsAtPath:iniPath]) {
- // the file does not exist; there is nothing to run
- [pool release];
- return;
- }
-
- int readResult;
- char values[2][MAX_TEXT_LEN];
- readResult = ReadStrings([iniPath UTF8String],
- "ExeRelPath\0ExeArg\0",
- 2,
- values,
- "PostUpdateMac");
- if (readResult) {
- [pool release];
- return;
- }
-
- NSString *exeRelPath = [NSString stringWithUTF8String:values[0]];
- NSString *exeArg = [NSString stringWithUTF8String:values[1]];
- if (!exeArg || !exeRelPath) {
- [pool release];
- return;
- }
-
- NSString* exeFullPath = [NSString stringWithUTF8String:aAppBundle];
- exeFullPath = [exeFullPath stringByAppendingPathComponent:exeRelPath];
-
- char optVals[1][MAX_TEXT_LEN];
- readResult = ReadStrings([iniPath UTF8String],
- "ExeAsync\0",
- 1,
- optVals,
- "PostUpdateMac");
-
- NSTask *task = [[NSTask alloc] init];
- [task setLaunchPath:exeFullPath];
- [task setArguments:[NSArray arrayWithObject:exeArg]];
- [task launch];
- if (!readResult) {
- NSString *exeAsync = [NSString stringWithUTF8String:optVals[0]];
- if ([exeAsync isEqualToString:@"false"]) {
- [task waitUntilExit];
- }
- }
- // ignore the return value of the task, there's nothing we can do with it
- [task release];
-
- [pool release];
-}
diff --git a/onlineupdate/source/update/updater/loaddlls.cxx b/onlineupdate/source/update/updater/loaddlls.cxx
deleted file mode 100644
index 6a0c8a61ee91..000000000000
--- a/onlineupdate/source/update/updater/loaddlls.cxx
+++ /dev/null
@@ -1,119 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-
-#ifdef _WIN32
-#ifndef UNICODE
-#define UNICODE
-#endif
-#include <windows.h>
-
-// Delayed load libraries are loaded when the first symbol is used.
-// The following ensures that we load the delayed loaded libraries from the
-// system directory.
-struct AutoLoadSystemDependencies
-{
- AutoLoadSystemDependencies()
- {
- // Remove the current directory from the search path for dynamically loaded
- // DLLs as a precaution. This call has no effect for delay load DLLs.
- SetDllDirectory(L"");
-
- HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
- if (module)
- {
- // SetDefaultDllDirectories is always available on Windows 8 and above. It
- // is also available on Windows Vista, Windows Server 2008, and
- // Windows 7 when MS KB2533623 has been applied.
- decltype(SetDefaultDllDirectories)* setDefaultDllDirectories =
- (decltype(SetDefaultDllDirectories)*) GetProcAddress(module, "SetDefaultDllDirectories");
- if (setDefaultDllDirectories)
- {
- setDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
- return;
- }
- }
-
- // TODO: moggi: do we need all that code?
- // When SetDefaultDllDirectories is not available, fallback to preloading
- // dlls. The order that these are loaded does not matter since they are
- // loaded using the LOAD_WITH_ALTERED_SEARCH_PATH flag.
-#ifdef HAVE_64BIT_BUILD
- // DLLs for Firefox x64 on Windows 7 (x64).
- // Note: dwmapi.dll is preloaded since a crash will try to load it from the
- // application's directory.
- static LPCWSTR delayDLLs[] = { L"apphelp.dll",
- L"cryptbase.dll",
- L"cryptsp.dll",
- L"dwmapi.dll",
- L"mpr.dll",
- L"ntmarta.dll",
- L"profapi.dll",
- L"propsys.dll",
- L"sspicli.dll",
- L"wsock32.dll"
- };
-
-#else
- // DLLs for Firefox x86 on Windows XP through Windows 7 (x86 and x64).
- // Note: dwmapi.dll is preloaded since a crash will try to load it from the
- // application's directory.
- static LPCWSTR delayDLLs[] = { L"apphelp.dll",
- L"crypt32.dll",
- L"cryptbase.dll",
- L"cryptsp.dll",
- L"dwmapi.dll",
- L"mpr.dll",
- L"msasn1.dll",
- L"ntmarta.dll",
- L"profapi.dll",
- L"propsys.dll",
- L"psapi.dll",
- L"secur32.dll",
- L"sspicli.dll",
- L"userenv.dll",
- L"uxtheme.dll",
- L"ws2_32.dll",
- L"ws2help.dll",
- L"wsock32.dll"
- };
-#endif
-
- WCHAR systemDirectory[MAX_PATH + 1] = { L'\0' };
- // If GetSystemDirectory fails we accept that we'll load the DLLs from the
- // normal search path.
- GetSystemDirectoryW(systemDirectory, MAX_PATH + 1);
- size_t systemDirLen = wcslen(systemDirectory);
-
- // Make the system directory path terminate with a slash
- if (systemDirectory[systemDirLen - 1] != L'\\' && systemDirLen)
- {
- systemDirectory[systemDirLen] = L'\\';
- ++systemDirLen;
- // No need to re-null terminate
- }
-
- // For each known DLL ensure it is loaded from the system32 directory
- for (size_t i = 0; i < sizeof(delayDLLs) / sizeof(delayDLLs[0]); ++i)
- {
- size_t fileLen = wcslen(delayDLLs[i]);
- wcsncpy(systemDirectory + systemDirLen, delayDLLs[i],
- MAX_PATH - systemDirLen);
- if (systemDirLen + fileLen <= MAX_PATH)
- {
- systemDirectory[systemDirLen + fileLen] = L'\0';
- }
- else
- {
- systemDirectory[MAX_PATH] = L'\0';
- }
- LPCWSTR fullModulePath = systemDirectory; // just for code readability
- // LOAD_WITH_ALTERED_SEARCH_PATH makes a dll look in its own directory for
- // dependencies and is only available on Win 7 and below.
- LoadLibraryExW(fullModulePath, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
- }
- }
-} loadDLLs;
-#endif
diff --git a/onlineupdate/source/update/updater/macbuild/Contents/Info.plist b/onlineupdate/source/update/updater/macbuild/Contents/Info.plist
deleted file mode 100644
index f104b55b9920..000000000000
--- a/onlineupdate/source/update/updater/macbuild/Contents/Info.plist
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleExecutable</key>
- <string>updater</string>
- <key>CFBundleIconFile</key>
- <string>updater.icns</string>
- <key>CFBundleIdentifier</key>
- <string>org.mozilla.updater</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleVersion</key>
- <string>1.0</string>
- <key>NSMainNibFile</key>
- <string>MainMenu</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
- <key>LSMinimumSystemVersion</key>
- <string>10.5</string>
- <key>LSMinimumSystemVersionByArchitecture</key>
- <dict>
- <key>i386</key>
- <string>10.5.0</string>
- <key>x86_64</key>
- <string>10.6.0</string>
- </dict>
-</dict>
-</plist>
diff --git a/onlineupdate/source/update/updater/macbuild/Contents/PkgInfo b/onlineupdate/source/update/updater/macbuild/Contents/PkgInfo
deleted file mode 100644
index bd04210fb49f..000000000000
--- a/onlineupdate/source/update/updater/macbuild/Contents/PkgInfo
+++ /dev/null
@@ -1 +0,0 @@
-APPL???? \ No newline at end of file
diff --git a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in b/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
deleted file mode 100644
index bca4022e755a..000000000000
--- a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
+++ /dev/null
@@ -1,7 +0,0 @@
-/* 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/. */
-
-/* Localized versions of Info.plist keys */
-
-CFBundleName = "%APP_NAME% Software Update";
diff --git a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib b/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib
deleted file mode 100644
index 6cfb50406bcf..000000000000
--- a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- IBClasses = (
- {
- CLASS = FirstResponder;
- LANGUAGE = ObjC;
- SUPERCLASS = NSObject;
-},
- {
- CLASS = UpdaterUI;
- LANGUAGE = ObjC;
- OUTLETS = {
- progressBar = NSProgressIndicator;
- progressTextField = NSTextField;
- };
- SUPERCLASS = NSObject;
-}
- );
- IBVersion = 1;
-} \ No newline at end of file
diff --git a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib b/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib
deleted file mode 100644
index 15091783707b..000000000000
--- a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>IBDocumentLocation</key>
- <string>111 162 356 240 0 0 1440 878 </string>
- <key>IBEditorPositions</key>
- <dict>
- <key>29</key>
- <string>106 299 84 44 0 0 1440 878 </string>
- </dict>
- <key>IBFramework Version</key>
- <string>489.0</string>
- <key>IBOpenObjects</key>
- <array>
- <integer>21</integer>
- <integer>29</integer>
- </array>
- <key>IBSystem Version</key>
- <string>10J567</string>
-</dict>
-</plist>
diff --git a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib b/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib
deleted file mode 100644
index 61ff026009dc..000000000000
--- a/onlineupdate/source/update/updater/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib
+++ /dev/null
Binary files differ
diff --git a/onlineupdate/source/update/updater/macbuild/Contents/Resources/updater.icns b/onlineupdate/source/update/updater/macbuild/Contents/Resources/updater.icns
deleted file mode 100644
index d7499c6692db..000000000000
--- a/onlineupdate/source/update/updater/macbuild/Contents/Resources/updater.icns
+++ /dev/null
Binary files differ
diff --git a/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx b/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx
deleted file mode 100644
index 2878aa2f0bb7..000000000000
--- a/onlineupdate/source/update/updater/progressui-unused/progressui_gonk.cxx
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=8 et :
- */
-/* 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/. */
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <string>
-
-#include "android/log.h"
-
-#include "progressui.h"
-
-#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoUpdater" , ## args)
-
-int InitProgressUI(int *argc, char ***argv)
-{
- return 0;
-}
-
-int ShowProgressUI()
-{
- LOG("Starting to apply update ...\n");
- return 0;
-}
-
-void QuitProgressUI()
-{
- LOG("Finished applying update\n");
-}
-
-void UpdateProgressUI(float progress)
-{
- assert(0.0f <= progress && progress <= 100.0f);
-
- static const size_t kProgressBarLength = 50;
- static size_t sLastNumBars;
- size_t numBars = size_t(float(kProgressBarLength) * progress / 100.0f);
- if (numBars == sLastNumBars)
- {
- return;
- }
- sLastNumBars = numBars;
-
- size_t numSpaces = kProgressBarLength - numBars;
- std::string bars(numBars, '=');
- std::string spaces(numSpaces, ' ');
- LOG("Progress [ %s%s ]\n", bars.c_str(), spaces.c_str());
-}
diff --git a/onlineupdate/source/update/updater/progressui-unused/progressui_osx.mm b/onlineupdate/source/update/updater/progressui-unused/progressui_osx.mm
deleted file mode 100644
index 8e3ce01eb836..000000000000
--- a/onlineupdate/source/update/updater/progressui-unused/progressui_osx.mm
+++ /dev/null
@@ -1,141 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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 <Cocoa/Cocoa.h>
-#include <stdio.h>
-#include <unistd.h>
-#include "progressui.h"
-#include "readstrings.h"
-#include "errors.h"
-
-#define TIMER_INTERVAL 0.2
-
-static float sProgressVal; // between 0 and 100
-static BOOL sQuit = FALSE;
-static StringTable sLabels;
-static const char *sUpdatePath;
-
-@interface UpdaterUI : NSObject
-{
- IBOutlet NSProgressIndicator *progressBar;
- IBOutlet NSTextField *progressTextField;
-}
-@end
-
-@implementation UpdaterUI
-
--(void)awakeFromNib
-{
- NSWindow *w = [progressBar window];
-
- [w setTitle:[NSString stringWithUTF8String:sLabels.title]];
- [progressTextField setStringValue:[NSString stringWithUTF8String:sLabels.info]];
-
- NSRect origTextFrame = [progressTextField frame];
- [progressTextField sizeToFit];
-
- int widthAdjust = progressTextField.frame.size.width - origTextFrame.size.width;
-
- if (widthAdjust > 0) {
- NSRect f;
- f.size.width = w.frame.size.width + widthAdjust;
- f.size.height = w.frame.size.height;
- [w setFrame:f display:YES];
- }
-
- [w center];
-
- [progressBar setIndeterminate:NO];
- [progressBar setDoubleValue:0.0];
-
- [[NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self
- selector:@selector(updateProgressUI:)
- userInfo:nil repeats:YES] retain];
-
- // Make sure we are on top initially
- [NSApp activateIgnoringOtherApps:YES];
-}
-
-// called when the timer goes off
--(void)updateProgressUI:(NSTimer *)aTimer
-{
- if (sQuit) {
- [aTimer invalidate];
- [aTimer release];
-
- // It seems to be necessary to activate and hide ourselves before we stop,
- // otherwise the "run" method will not return until the user focuses some
- // other app. The activate step is necessary if we are not the active app.
- // This is a big hack, but it seems to do the trick.
- [NSApp activateIgnoringOtherApps:YES];
- [NSApp hide:self];
- [NSApp stop:self];
- }
-
- float progress = sProgressVal;
-
- [progressBar setDoubleValue:(double)progress];
-}
-
-// leave this as returning a BOOL instead of NSApplicationTerminateReply
-// for backward compatibility
-- (BOOL)applicationShouldTerminate:(NSApplication *)sender
-{
- return sQuit;
-}
-
-@end
-
-int
-InitProgressUI(int *pargc, char ***pargv)
-{
- sUpdatePath = (*pargv)[1];
-
- return 0;
-}
-
-int
-ShowProgressUI()
-{
- // Only show the Progress UI if the process is taking a significant amount of
- // time where a significant amount of time is defined as .5 seconds after
- // ShowProgressUI is called sProgress is less than 70.
- usleep(500000);
-
- if (sQuit || sProgressVal > 70.0f)
- return 0;
-
- char path[PATH_MAX];
- snprintf(path, sizeof(path), "%s/updater.ini", sUpdatePath);
- if (ReadStrings(path, &sLabels) != OK)
- return -1;
-
- // Continue the update without showing the Progress UI if any of the supplied
- // strings are larger than MAX_TEXT_LEN (Bug 628829).
- if (!(strlen(sLabels.title) < MAX_TEXT_LEN - 1 &&
- strlen(sLabels.info) < MAX_TEXT_LEN - 1))
- return -1;
-
- [NSApplication sharedApplication];
- [NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
- [NSApp run];
-
- return 0;
-}
-
-// Called on a background thread
-void
-QuitProgressUI()
-{
- sQuit = TRUE;
-}
-
-// Called on a background thread
-void
-UpdateProgressUI(float progress)
-{
- sProgressVal = progress; // 32-bit writes are atomic
-}
diff --git a/onlineupdate/source/update/updater/progressui.h b/onlineupdate/source/update/updater/progressui.h
deleted file mode 100644
index a3e4913fc32f..000000000000
--- a/onlineupdate/source/update/updater/progressui.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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 PROGRESSUI_H__
-#define PROGRESSUI_H__
-
-#include "updatedefines.h"
-#include "types.hxx"
-
-#if defined(_WIN32)
-#define NS_main wmain
-#else
-#define NS_main main
-#endif
-
-// Called to perform any initialization of the widget toolkit
-int InitProgressUI(int* argc, NS_tchar*** argv);
-
-#if defined(_WIN32)
-// Called on the main thread at startup
-int ShowProgressUI(bool indeterminate = false, bool initUIStrings = true);
-int InitProgressUIStrings();
-#else
-// Called on the main thread at startup
-int ShowProgressUI();
-#endif
-// May be called from any thread
-void QuitProgressUI();
-
-// May be called from any thread: progress is a number between 0 and 100
-void UpdateProgressUI(float progress);
-
-#endif // PROGRESSUI_H__
diff --git a/onlineupdate/source/update/updater/progressui_gtk.cxx b/onlineupdate/source/update/updater/progressui_gtk.cxx
deleted file mode 100644
index 961e4cdd92b9..000000000000
--- a/onlineupdate/source/update/updater/progressui_gtk.cxx
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#if defined(UNIX) || defined(MACOSX)
-#include <stdio.h>
-#include <gtk/gtk.h>
-#include <unistd.h>
-#include "progressui.h"
-#include "readstrings.h"
-#include "errors.h"
-#include <string.h>
-#include "progressui_gtk_icon.h"
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-#define TIMER_INTERVAL 100
-
-static float sProgressVal; // between 0 and 100
-static gboolean sQuit = FALSE;
-static gboolean sEnableUI;
-static guint sTimerID;
-
-static GtkWidget *sWin;
-static GtkWidget *sLabel;
-static GtkWidget *sProgressBar;
-
-static const char *sProgramPath;
-
-static gboolean
-UpdateDialog(gpointer /*data*/)
-{
- if (sQuit)
- {
- gtk_widget_hide(sWin);
- gtk_main_quit();
- }
-
- float progress = sProgressVal;
-
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(sProgressBar),
- progress / 100.0);
-
- return TRUE;
-}
-
-static gboolean
-OnDeleteEvent(GtkWidget * /*widget*/, GdkEvent * /*event*/, gpointer /*user_data*/)
-{
- return TRUE;
-}
-
-int
-InitProgressUI(int *pargc, char ***pargv)
-{
- sProgramPath = (*pargv)[0];
-
- sEnableUI = gtk_init_check(pargc, pargv);
- return 0;
-}
-
-int
-ShowProgressUI()
-{
- if (!sEnableUI)
- return -1;
-
- // Only show the Progress UI if the process is taking a significant amount of
- // time where a significant amount of time is defined as .5 seconds after
- // ShowProgressUI is called sProgress is less than 70.
- usleep(500000);
-
- if (sQuit || sProgressVal > 70.0f)
- return 0;
-
- char ini_path[PATH_MAX];
- snprintf(ini_path, sizeof(ini_path), "%s.ini", sProgramPath);
-
- StringTable strings;
- if (ReadStrings(ini_path, &strings) != OK)
- {
- strcpy(strings.title, "LibreOffice Update");
- strcpy(strings.info, "Please wait while we update your installation.");
- }
-
- sWin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- if (!sWin)
- return -1;
-
- static GdkPixbuf *pixbuf;
-
- g_signal_connect(G_OBJECT(sWin), "delete_event",
- G_CALLBACK(OnDeleteEvent), nullptr);
-
- gtk_window_set_title(GTK_WINDOW(sWin), strings.title);
- gtk_window_set_type_hint(GTK_WINDOW(sWin), GDK_WINDOW_TYPE_HINT_DIALOG);
- gtk_window_set_position(GTK_WINDOW(sWin), GTK_WIN_POS_CENTER_ALWAYS);
- gtk_window_set_resizable(GTK_WINDOW(sWin), FALSE);
- gtk_window_set_decorated(GTK_WINDOW(sWin), TRUE);
- gtk_window_set_deletable(GTK_WINDOW(sWin),FALSE);
- pixbuf = gdk_pixbuf_new_from_xpm_data (icon_data);
- gtk_window_set_icon(GTK_WINDOW(sWin), pixbuf);
- g_object_unref(pixbuf);
-
- GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
- gtk_box_set_homogeneous(GTK_BOX(vbox), true);
- sLabel = gtk_label_new(strings.info);
- gtk_misc_set_alignment(GTK_MISC(sLabel), 0.0f, 0.0f);
- sProgressBar = gtk_progress_bar_new();
-
- gtk_box_pack_start(GTK_BOX(vbox), sLabel, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), sProgressBar, TRUE, TRUE, 0);
-
- sTimerID = g_timeout_add(TIMER_INTERVAL, UpdateDialog, nullptr);
-
- gtk_container_set_border_width(GTK_CONTAINER(sWin), 10);
- gtk_container_add(GTK_CONTAINER(sWin), vbox);
- gtk_widget_show_all(sWin);
-
- gtk_main();
- return 0;
-}
-
-// Called on a background thread
-void
-QuitProgressUI()
-{
- sQuit = TRUE;
-}
-
-// Called on a background thread
-void
-UpdateProgressUI(float progress)
-{
- sProgressVal = progress; // 32-bit writes are atomic
-}
-
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-#endif // defined(UNIX) || defined(MACOSX)
diff --git a/onlineupdate/source/update/updater/progressui_gtk_icon.h b/onlineupdate/source/update/updater/progressui_gtk_icon.h
deleted file mode 100644
index 6660c071f0b1..000000000000
--- a/onlineupdate/source/update/updater/progressui_gtk_icon.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* XPM */
-static const char *icon_data[] = {
-/* columns rows colors chars-per-pixel */
-"32 32 167 2 ",
-" c #915B05",
-". c #955F0C",
-"X c #95610D",
-"o c #8F6013",
-"O c #8C601D",
-"+ c #966311",
-"@ c #9A6615",
-"# c #9A6817",
-"$ c #9C6B1D",
-"% c #8B652A",
-"& c #966B26",
-"* c #976D28",
-"= c #9C7129",
-"- c #8E6D34",
-"; c #A17025",
-": c #A2752E",
-"> c #AB7A2B",
-", c #A77A34",
-"< c #A97C33",
-"1 c #8D7751",
-"2 c #8D7A57",
-"3 c #8A7658",
-"4 c #A17D42",
-"5 c #8E7E63",
-"6 c #AE823B",
-"7 c #B88635",
-"8 c #B2853B",
-"9 c #BB8A3A",
-"0 c #C08B36",
-"q c #AA864A",
-"w c #AF894D",
-"e c #BC8D42",
-"r c #AA8B57",
-"t c #B38F56",
-"y c #B79256",
-"u c #968468",
-"i c #958A73",
-"p c #9B8970",
-"a c #938D7D",
-"s c #9D927A",
-"d c #A3916F",
-"f c #AD966D",
-"g c #B1996D",
-"h c #BF9F6E",
-"j c #A89473",
-"k c #B59D75",
-"l c #BEA375",
-"z c #C08F42",
-"x c #D29E4B",
-"c c #C69C5C",
-"v c #DBA44D",
-"b c #D5A351",
-"n c #DCA651",
-"m c #DFAA56",
-"M c #D8A75A",
-"N c #DCAA5B",
-"B c #C79E60",
-"V c #C09F6E",
-"C c #C8A162",
-"Z c #CCA66A",
-"A c #DEAE62",
-"S c #D6AD6E",
-"D c #DEB16A",
-"F c #C1A272",
-"G c #C6AA7E",
-"H c #D3AE73",
-"J c #D8AF71",
-"K c #DEB676",
-"L c #D8B47C",
-"P c #E2B266",
-"I c #E3B36A",
-"U c #E5B974",
-"Y c #E3BB7C",
-"T c #8B8C85",
-"R c #8D8E88",
-"E c #918F83",
-"W c #8F908C",
-"Q c #9A9483",
-"! c #92938E",
-"~ c #98968B",
-"^ c #9E9788",
-"/ c #939591",
-"( c #969894",
-") c #9C9A94",
-"_ c #9C9E99",
-"` c #A19C94",
-"' c #A29E99",
-"] c #9FA19C",
-"[ c #ADA189",
-"{ c #B9A486",
-"} c #AEA695",
-"| c #A1A29C",
-" . c #A9A89F",
-".. c #B7AE98",
-"X. c #A4A6A2",
-"o. c #A6A9A4",
-"O. c #AAABA7",
-"+. c #ACACA9",
-"@. c #AEB1AB",
-"#. c #B0B2AE",
-"$. c #B3B5B1",
-"%. c #B6B8B2",
-"&. c #B9BBB7",
-"*. c #BBBCBA",
-"=. c #C3AD8A",
-"-. c #CDB288",
-";. c #C9B495",
-":. c #D3BC96",
-">. c #E3BD84",
-",. c #E1BF88",
-"<. c #D2BEA0",
-"1. c #C8BFB0",
-"2. c #BFC1BB",
-"3. c #D8C095",
-"4. c #E5C087",
-"5. c #EAC385",
-"6. c #E6C289",
-"7. c #E8C288",
-"8. c #E4C492",
-"9. c #E6C99B",
-"0. c #EBCD9E",
-"q. c #D4C1A5",
-"w. c #D8C5A7",
-"e. c #CBC2B1",
-"r. c #C1C4BE",
-"t. c #D1C7B7",
-"y. c #DFCEB4",
-"u. c #E7CDA5",
-"i. c #EDD0A3",
-"p. c #E6D0AF",
-"a. c #EED5AC",
-"s. c #E6D2B0",
-"d. c #EDD6B3",
-"f. c #EBD7B9",
-"g. c #ECD9BC",
-"h. c #F3DBB5",
-"j. c #C4C5C3",
-"k. c #C6C9C3",
-"l. c #C9CCC6",
-"z. c #CCCDCA",
-"x. c #D4CFC3",
-"c. c #CFD0CC",
-"v. c #D1D2CF",
-"b. c #D3D4D3",
-"n. c #D6D8D5",
-"m. c #DADAD6",
-"M. c #DADBDA",
-"N. c #E7D8C0",
-"B. c #ECDCC2",
-"V. c #DFE1DE",
-"C. c #F3E1C3",
-"Z. c #F2E4CC",
-"A. c #ECE2D4",
-"S. c #EEE7DA",
-"D. c #F1E5D2",
-"F. c #F7E9D6",
-"G. c #F0E8DC",
-"H. c #E3E3E3",
-"J. c #E7E8E7",
-"K. c #E8E8E7",
-"L. c #ECECEB",
-"P. c #F4EFE6",
-"I. c #F5F1EB",
-"U. c #F3F4F3",
-"Y. c #F8F5F1",
-"T. c #FAF9F7",
-"R. c #FFFFFF",
-/* pixels */
-"R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.F X ; A.R.R.R.R.R.R.",
-"R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.< u.H # S.R.R.R.R.R.",
-"R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.T.y.F l R., d.a.Z # G.R.R.R.R.",
-"R.R.R.R.R.R.R.R.R.R.R.R.R.R.A.V , + w :., y.< f.Y 8.C # P.R.R.R.",
-"R.R.R.R.R.R.R.R.R.R.R.R.R.G : -.N.I.Y.T.t X . f.5.n 4.e # T.R.R.",
-"R.R.R.R.R.R.R.R.R.R.R.R.R.$ p.F.Z.Z.D.Y.F ..l s.h.U D 6.# :.R.R.",
-"R.R.R.R.R.R.R.R.R.R.R.U.l.* u.d.i.d.B.I.y k 3., C.5.N >.> h R.R.",
-"R.R.R.R.R.R.R.R.R.U.%.W ] , 8.0.0.| R T T T T T T ~ Q >.< h R.R.",
-"R.R.R.R.R.R.R.R.n.W ] 2.k.q 3.h.a.| v.U.U.L.L.L.L.U.o.9.< V R.R.",
-"R.R.R.R.R.R.R.z.R @.j.k.z.q K 6 ) M.R.R.R.R.R.R.R.o.L > F R.R.",
-"R.R.R.R.R.R.M.W $.2.k.l.j.r 0.8.6.! b.R.R.R.R.R.R.R.o.p.8 -.R.R.",
-"R.R.R.R.R.T.! @.2.k.l.O.W 6 4.I N E j.R.R.R.R.R.$./ T J 9 w.R.R.",
-"R.R.R.R.R.*._ 2.r.l.] X.U., Y A v a k.R.R.L.R.R.U.E 0 x 7 w.R.R.",
-"R.R.R.R.R.! %.r.k.@.| T.R., Y N v a j.R.R.@.U.R.R.*.r b 7 <.R.R.",
-"R.R.R.R.n.! r.k.k.W L.R.R., Y A v f M.R.R.O.&.R.R.H.a M 9 ;.T.R.",
-"R.R.R.R.&.X.j.l.$.O.R.R.T., Y P n g M.R.R.o.W R.R.R.R D 9 { L.T.",
-"R.R.w + 2 @.l.c. .1 + . q.: >.P m g ! ! / T E L.R.R._ K e j H.R.",
-"R.R.6 Z. .%.c.b.' <.a.c =.= Y P m N M M M M s H.R.R.X.>.z u n.T.",
-"R.R., Z.} $.v.n.O.=.i.c { * U 7.7.5.7.4.4.4.Q L.R.R.] ,.8 5 n.T.",
-"R.R.6 Z...@.n.M.&.[ i.B =.5 . @ @ @ @ @ @ # R T.R.R.! @ o ] V.T.",
-"R.R., A.x._ m.V.m.! G.:.;.z.+.' ` ` ` ^ ) W $.R.R.K.T ) $.b.U.R.",
-"R.T., L K R m.H.K.#.[ y ;.U.J.H.H.H.H.H.b.W L.R.R.j.+.H.L.U.R.R.",
-"R.M.& H A j #.K.L.L.| 1 + # # # # # $ t./ c.R.R.T./ H.R.T.R.R.R.",
-"L.O.O S 8.6.W M.U.T.Y.O.) e.g.f.a.w.d ! b.R.R.R.&.+.R.R.R.R.R.R.",
-"U.2.% - ( U.T.R.R.M.+.W R T _ *.U.R.R.R.b.( U.R.R.R.R.R.R.",
-"R.U.V.n.b.b.b.o._ L.R.R.R.R.R.T.R.R.R.R.R.R.z./ J.R.R.R.R.R.R.R.",
-"R.R.R.R.T.R.R.T.j./ c.R.R.R.R.R.R.R.R.R.U.#.( L.R.R.R.R.R.R.R.R.",
-"R.R.R.R.R.R.R.R.T.4 ^ ) j.J.T.R.R.U.M.$.! &.T.R.R.R.R.R.R.R.R.R.",
-"R.R.R.R.R.R.R.T.M.& H Z g a T R T E i Q L.R.R.R.R.R.R.R.R.R.R.R.",
-"R.R.R.R.R.R.R.U.+.O S ,.>.7.>.7.,.6.< 3 H.R.R.R.R.R.R.R.R.R.R.R.",
-"R.R.R.R.R.R.R.U.2.% # $ & $ $ $ $ & X p L.R.R.R.R.R.R.R.R.R.R.R.",
-"R.R.R.R.R.R.R.R.Y.m.e.1.1.1.1.1.1.e.t.L.R.R.R.R.R.R.R.R.R.R.R.R."
-};
diff --git a/onlineupdate/source/update/updater/progressui_null.cxx b/onlineupdate/source/update/updater/progressui_null.cxx
deleted file mode 100644
index 66d294a133a0..000000000000
--- a/onlineupdate/source/update/updater/progressui_null.cxx
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#if !defined(MACOSX) && !defined(UNIX) && !defined(_WIN32)
-#include "progressui.h"
-
-int InitProgressUI(int *argc, char ***argv)
-{
- return 0;
-}
-
-int ShowProgressUI()
-{
- return 0;
-}
-
-void QuitProgressUI()
-{
-}
-
-void UpdateProgressUI(float progress)
-{
-}
-#endif // !defined(MACOSX) && !defined(UNIX) && !defined(_WIN32)
diff --git a/onlineupdate/source/update/updater/progressui_win.cxx b/onlineupdate/source/update/updater/progressui_win.cxx
deleted file mode 100644
index 7ef23cfabfdf..000000000000
--- a/onlineupdate/source/update/updater/progressui_win.cxx
+++ /dev/null
@@ -1,348 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#ifdef _WIN32
-#include <stdio.h>
-#ifndef UNICODE
-#define UNICODE
-#endif
-#include <windows.h>
-#include <commctrl.h>
-#include <process.h>
-#include <io.h>
-
-#include "resource.h"
-#include "progressui.h"
-#include "readstrings.h"
-#include "errors.h"
-
-#define TIMER_ID 1
-#define TIMER_INTERVAL 100
-
-#define RESIZE_WINDOW(hwnd, extrax, extray) \
- { \
- RECT windowSize; \
- GetWindowRect(hwnd, &windowSize); \
- SetWindowPos(hwnd, 0, 0, 0, windowSize.right - windowSize.left + extrax, \
- windowSize.bottom - windowSize.top + extray, \
- SWP_NOMOVE | SWP_NOZORDER); \
- }
-
-#define MOVE_WINDOW(hwnd, dx, dy) \
- { \
- RECT rc; \
- POINT pt; \
- GetWindowRect(hwnd, &rc); \
- pt.x = rc.left; \
- pt.y = rc.top; \
- ScreenToClient(GetParent(hwnd), &pt); \
- SetWindowPos(hwnd, 0, pt.x + dx, pt.y + dy, 0, 0, \
- SWP_NOSIZE | SWP_NOZORDER); \
- }
-
-static float sProgress; // between 0 and 100
-static BOOL sQuit = FALSE;
-static BOOL sIndeterminate = FALSE;
-static StringTable sUIStrings;
-
-static BOOL
-GetStringsFile(WCHAR filename[MAX_PATH])
-{
- if (!GetModuleFileNameW(nullptr, filename, MAX_PATH))
- return FALSE;
-
- WCHAR *dot = wcsrchr(filename, '.');
- if (!dot || wcsicmp(dot + 1, L"exe"))
- return FALSE;
-
- wcscpy(dot + 1, L"ini");
- return TRUE;
-}
-
-static void
-UpdateDialog(HWND hDlg)
-{
- int pos = int(sProgress + 0.5f);
- HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
- SendMessage(hWndPro, PBM_SETPOS, pos, 0);
-}
-
-// The code in this function is from MSDN:
-// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/usingdialogboxes.asp
-static void
-CenterDialog(HWND hDlg)
-{
- RECT rc, rcOwner, rcDlg;
-
- // Get the owner window and dialog box rectangles.
- HWND desktop = GetDesktopWindow();
-
- GetWindowRect(desktop, &rcOwner);
- GetWindowRect(hDlg, &rcDlg);
- CopyRect(&rc, &rcOwner);
-
- // Offset the owner and dialog box rectangles so that
- // right and bottom values represent the width and
- // height, and then offset the owner again to discard
- // space taken up by the dialog box.
-
- OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
- OffsetRect(&rc, -rc.left, -rc.top);
- OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
-
- // The new position is the sum of half the remaining
- // space and the owner's original position.
-
- SetWindowPos(hDlg,
- HWND_TOP,
- rcOwner.left + (rc.right / 2),
- rcOwner.top + (rc.bottom / 2),
- 0, 0, // ignores size arguments
- SWP_NOSIZE);
-}
-
-static void
-InitDialog(HWND hDlg)
-{
- WCHAR szwTitle[MAX_TEXT_LEN];
- WCHAR szwInfo[MAX_TEXT_LEN];
-
- MultiByteToWideChar(CP_UTF8, 0, sUIStrings.title, -1, szwTitle,
- sizeof(szwTitle)/sizeof(szwTitle[0]));
- MultiByteToWideChar(CP_UTF8, 0, sUIStrings.info, -1, szwInfo,
- sizeof(szwInfo)/sizeof(szwInfo[0]));
-
- SetWindowTextW(hDlg, szwTitle);
- SetWindowTextW(GetDlgItem(hDlg, IDC_INFO), szwInfo);
-
- // Set dialog icon
- HICON hIcon = LoadIcon(GetModuleHandle(nullptr),
- MAKEINTRESOURCE(IDI_DIALOG));
- if (hIcon)
- SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
-
- HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
- SendMessage(hWndPro, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
- if (sIndeterminate)
- {
- LONG_PTR val = GetWindowLongPtr(hWndPro, GWL_STYLE);
- SetWindowLongPtr(hWndPro, GWL_STYLE, val|PBS_MARQUEE);
- SendMessage(hWndPro,(UINT) PBM_SETMARQUEE,(WPARAM) TRUE,(LPARAM)50 );
- }
-
- // Resize the dialog to fit all of the text if necessary.
- RECT infoSize, textSize;
- HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO);
-
- // Get the control's font for calculating the new size for the control
- HDC hDCInfo = GetDC(hWndInfo);
- HFONT hInfoFont;
- HFONT hOldFont = 0;
- hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0);
-
- if (hInfoFont)
- hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont);
-
- // Measure the space needed for the text on a single line. DT_CALCRECT means
- // nothing is drawn.
- if (DrawText(hDCInfo, szwInfo, -1, &textSize,
- DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE))
- {
- GetClientRect(hWndInfo, &infoSize);
- SIZE extra;
- // Calculate the additional space needed for the text by subtracting from
- // the rectangle returned by DrawText the existing client rectangle's width
- // and height.
- extra.cx = (textSize.right - textSize.left) - \
- (infoSize.right - infoSize.left);
- extra.cy = (textSize.bottom - textSize.top) - \
- (infoSize.bottom - infoSize.top);
- if (extra.cx < 0)
- extra.cx = 0;
- if (extra.cy < 0)
- extra.cy = 0;
- if ((extra.cx > 0) || (extra.cy > 0))
- {
- RESIZE_WINDOW(hDlg, extra.cx, extra.cy);
- RESIZE_WINDOW(hWndInfo, extra.cx, extra.cy);
- RESIZE_WINDOW(hWndPro, extra.cx, 0);
- MOVE_WINDOW(hWndPro, 0, extra.cy);
- }
- }
-
- if (hOldFont)
- SelectObject(hDCInfo, hOldFont);
-
- ReleaseDC(hWndInfo, hDCInfo);
-
- CenterDialog(hDlg); // make dialog appear in the center of the screen
-
- SetTimer(hDlg, TIMER_ID, TIMER_INTERVAL, nullptr);
-}
-
-// Message handler for update dialog.
-static LRESULT CALLBACK
-DialogProc(HWND hDlg, UINT message, WPARAM /*wParam*/, LPARAM /*lParam*/)
-{
- switch (message)
- {
- case WM_INITDIALOG:
- InitDialog(hDlg);
- return TRUE;
-
- case WM_TIMER:
- if (sQuit)
- {
- EndDialog(hDlg, 0);
- }
- else
- {
- UpdateDialog(hDlg);
- }
- return TRUE;
-
- case WM_COMMAND:
- return TRUE;
- }
- return FALSE;
-}
-
-int
-InitProgressUI(int* /*argc*/, WCHAR*** /*argv*/)
-{
- return 0;
-}
-
-/**
- * Initializes the progress UI strings
- *
- * @return 0 on success, -1 on error
-*/
-int
-InitProgressUIStrings()
-{
- // If we do not have updater.ini, then we should not bother showing UI.
- WCHAR filename[MAX_PATH];
- if (!GetStringsFile(filename))
- {
- strcpy(sUIStrings.title, "LibreOffice Update");
- strcpy(sUIStrings.info, "Please wait while we update your installation.");
- return 0;
- }
-
- if (_waccess(filename, 04))
- {
- strcpy(sUIStrings.title, "LibreOffice Update");
- strcpy(sUIStrings.info, "Please wait while we update your installation.");
- return 0;
- }
-
- // If the updater.ini doesn't have the required strings, then we should not
- // bother showing UI.
- if (ReadStrings(filename, &sUIStrings) != OK)
- {
- strcpy(sUIStrings.title, "LibreOffice Update");
- strcpy(sUIStrings.info, "Please wait while we update your installation.");
- }
-
- return 0;
-}
-
-int
-ShowProgressUI(bool indeterminate, bool initUIStrings)
-{
- sIndeterminate = indeterminate;
- if (!indeterminate)
- {
- // Only show the Progress UI if the process is taking a significant amount of
- // time where a significant amount of time is defined as .5 seconds after
- // ShowProgressUI is called sProgress is less than 70.
- Sleep(500);
-
- if (sQuit || sProgress > 70.0f)
- return 0;
- }
-
- // Don't load the UI if there's an <exe_name>.Local directory for redirection.
- WCHAR appPath[MAX_PATH + 1] = { L'\0' };
- if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH))
- {
- return -1;
- }
-
- if (wcslen(appPath) + wcslen(L".Local") >= MAX_PATH)
- {
- return -1;
- }
-
- wcscat(appPath, L".Local");
-
- if (!_waccess(appPath, 04))
- {
- return -1;
- }
-
- // Don't load the UI if the strings for the UI are not provided.
- if (initUIStrings && InitProgressUIStrings() == -1)
- {
- return -1;
- }
-
- if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH))
- {
- return -1;
- }
-
- // Use an activation context that supports visual styles for the controls.
- ACTCTXW actx = {0};
- actx.cbSize = sizeof(ACTCTXW);
- actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
- actx.hModule = GetModuleHandle(NULL); // Use the embedded manifest
- // This is needed only for Win XP but doesn't cause a problem with other
- // versions of Windows.
- actx.lpSource = appPath;
- actx.lpResourceName = MAKEINTRESOURCE(IDR_COMCTL32_MANIFEST);
-
- HANDLE hactx = CreateActCtxW(&actx);
- ULONG_PTR actxCookie = NULL;
- if (hactx != INVALID_HANDLE_VALUE)
- {
- // Push the specified activation context to the top of the activation stack.
- ActivateActCtx(hactx, &actxCookie);
- }
-
- INITCOMMONCONTROLSEX icc =
- {
- sizeof(INITCOMMONCONTROLSEX),
- ICC_PROGRESS_CLASS
- };
- InitCommonControlsEx(&icc);
-
- DialogBox(GetModuleHandle(nullptr),
- MAKEINTRESOURCE(IDD_DIALOG), nullptr,
- (DLGPROC) DialogProc);
-
- if (hactx != INVALID_HANDLE_VALUE)
- {
- // Deactivate the context now that the comctl32.dll is loaded.
- DeactivateActCtx(0, actxCookie);
- }
-
- return 0;
-}
-
-void
-QuitProgressUI()
-{
- sQuit = TRUE;
-}
-
-void
-UpdateProgressUI(float progress)
-{
- sProgress = progress; // 32-bit writes are atomic
-}
-#endif // _WIN32
diff --git a/onlineupdate/source/update/updater/resource.h b/onlineupdate/source/update/updater/resource.h
deleted file mode 100644
index 6b6091c7b8bb..000000000000
--- a/onlineupdate/source/update/updater/resource.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 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/. */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by updater.rc
-//
-#define IDD_DIALOG 101
-#define IDC_PROGRESS 1000
-#define IDC_INFO 1002
-#define IDI_DIALOG 1003
-#define TYPE_CERT 512
-#define IDR_PRIMARY_CERT 1004
-#define IDR_BACKUP_CERT 1005
-#define IDS_UPDATER_IDENTITY 1006
-#define IDR_XPCSHELL_CERT 1007
-#define IDR_COMCTL32_MANIFEST 17
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 102
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1008
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/onlineupdate/source/update/updater/updater-common.build b/onlineupdate/source/update/updater/updater-common.build
deleted file mode 100644
index 6516a4843c43..000000000000
--- a/onlineupdate/source/update/updater/updater-common.build
+++ /dev/null
@@ -1,119 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-srcs = [
- 'archivereader.cpp',
- 'bspatch.cpp',
- 'updater.cpp',
-]
-
-have_progressui = 0
-
-if CONFIG['VERIFY_MAR_SIGNATURE']:
- USE_LIBS += [
- 'verifymar',
- ]
-
-if CONFIG['OS_ARCH'] == 'WINNT':
- have_progressui = 1
- srcs += [
- 'loaddlls.cpp',
- 'progressui_win.cpp',
- 'win_dirent.cpp',
- ]
- RCINCLUDE = '%supdater.rc' % updater_rel_path
- DEFINES['UNICODE'] = True
- DEFINES['_UNICODE'] = True
- DEFINES['NOMINMAX'] = True
- USE_STATIC_LIBS = True
-
- # Pick up nsWindowsRestart.cpp
- LOCAL_INCLUDES += [
- '/toolkit/xre',
- ]
- USE_LIBS += [
- 'updatecommon-standalone',
- ]
- OS_LIBS += [
- 'comctl32',
- 'ws2_32',
- 'shell32',
- 'shlwapi',
- 'crypt32',
- 'advapi32',
- ]
-elif CONFIG['OS_ARCH'] == 'Linux' and CONFIG['VERIFY_MAR_SIGNATURE']:
- USE_LIBS += [
- 'nss',
- 'signmar',
- 'updatecommon',
- ]
- OS_LIBS += CONFIG['NSPR_LIBS']
-else:
- USE_LIBS += [
- 'updatecommon',
- ]
-
-USE_LIBS += [
- 'mar',
-]
-
-if CONFIG['MOZ_NATIVE_BZ2']:
- OS_LIBS += CONFIG['MOZ_BZ2_LIBS']
-else:
- USE_LIBS += [
- 'bz2',
- ]
-
-if CONFIG['MOZ_ENABLE_GTK']:
- have_progressui = 1
- srcs += [
- 'progressui_gtk.cpp',
- ]
-
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
- have_progressui = 1
- srcs += [
- 'launchchild_osx.mm',
- 'progressui_osx.mm',
- ]
- OS_LIBS += [
- '-framework Cocoa',
- '-framework Security',
- ]
-
-if have_progressui == 0:
- srcs += [
- 'progressui_null.cpp',
- ]
-
-SOURCES += sorted(srcs)
-
-DEFINES['NS_NO_XPCOM'] = True
-DISABLE_STL_WRAPPING = True
-for var in ('MAR_CHANNEL_ID', 'MOZ_APP_VERSION'):
- DEFINES[var] = '"%s"' % CONFIG[var]
-
-LOCAL_INCLUDES += [
- '/toolkit/mozapps/update/common',
- '/xpcom/glue',
-]
-
-DELAYLOAD_DLLS += [
- 'crypt32.dll',
- 'comctl32.dll',
- 'userenv.dll',
- 'wsock32.dll',
-]
-
-if CONFIG['_MSC_VER']:
- WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
-elif CONFIG['OS_ARCH'] == 'WINNT':
- WIN32_EXE_LDFLAGS += ['-municode']
-
-if CONFIG['MOZ_WIDGET_GTK']:
- CXXFLAGS += CONFIG['TK_CFLAGS']
- OS_LIBS += CONFIG['TK_LIBS']
diff --git a/onlineupdate/source/update/updater/updater-xpcshell/Makefile.in b/onlineupdate/source/update/updater/updater-xpcshell/Makefile.in
deleted file mode 100644
index 21364883435f..000000000000
--- a/onlineupdate/source/update/updater/updater-xpcshell/Makefile.in
+++ /dev/null
@@ -1,32 +0,0 @@
-# vim:set ts=8 sw=8 sts=8 noet:
-# 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/.
-
-# For changes here, also consider ../Makefile.in
-
-XPCSHELLTESTROOT = $(abspath $(DEPTH))/_tests/xpcshell/toolkit/mozapps/update/tests
-MOCHITESTROOT = $(abspath $(DEPTH))/_tests/testing/mochitest/chrome/toolkit/mozapps/update/tests
-
-include $(topsrcdir)/config/rules.mk
-
-libs::
-ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
- # Copy for xpcshell tests
- $(NSINSTALL) -D $(XPCSHELLTESTROOT)/data/updater-xpcshell.app
- rsync -a -C --exclude '*.in' $(srcdir)/../macbuild/Contents $(XPCSHELLTESTROOT)/data/updater-xpcshell.app
- sed -e 's/%APP_NAME%/$(MOZ_APP_DISPLAYNAME)/' $(srcdir)/../macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | \
- iconv -f UTF-8 -t UTF-16 > $(XPCSHELLTESTROOT)/data/updater-xpcshell.app/Contents/Resources/English.lproj/InfoPlist.strings
- $(NSINSTALL) -D $(XPCSHELLTESTROOT)/data/updater-xpcshell.app/Contents/MacOS/updater-xpcshell
- $(NSINSTALL) $(PROGRAM) $(XPCSHELLTESTROOT)/data/updater-xpcshell.app/Contents/MacOS
- rm -f $(PROGRAM)
- rm -Rf $(XPCSHELLTESTROOT)/data/updater.app
- mv $(XPCSHELLTESTROOT)/data/updater-xpcshell.app $(XPCSHELLTESTROOT)/data/updater.app
- mv $(XPCSHELLTESTROOT)/data/updater.app/Contents/MacOS/updater-xpcshell $(XPCSHELLTESTROOT)/data/updater.app/Contents/MacOS/updater
-
- # Copy for mochitest chrome tests
- rsync -a -C $(XPCSHELLTESTROOT)/data/updater.app $(MOCHITESTROOT)/data/updater.app
-else
- cp $(PROGRAM) $(XPCSHELLTESTROOT)/data/updater$(BIN_SUFFIX)
- cp $(PROGRAM) $(MOCHITESTROOT)/data/updater$(BIN_SUFFIX)
-endif
diff --git a/onlineupdate/source/update/updater/updater-xpcshell/moz.build b/onlineupdate/source/update/updater/updater-xpcshell/moz.build
deleted file mode 100644
index ba5c844cfc10..000000000000
--- a/onlineupdate/source/update/updater/updater-xpcshell/moz.build
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-Program('updater-xpcshell')
-
-updater_rel_path = '../'
-DIST_INSTALL = False
-DEFINES['TEST_UPDATER'] = True
-include('../updater-common.build')
-FAIL_ON_WARNINGS = True
diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx
deleted file mode 100644
index 321d43a53936..000000000000
--- a/onlineupdate/source/update/updater/updater.cxx
+++ /dev/null
@@ -1,4594 +0,0 @@
-/* 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/. */
-
-/**
- * Manifest Format
- * ---------------
- *
- * contents = 1*( line )
- * line = method LWS *( param LWS ) CRLF
- * CRLF = "\r\n"
- * LWS = 1*( " " | "\t" )
- *
- * Available methods for the manifest file:
- *
- * updatev2.manifest
- * -----------------
- * method = "add" | "add-if" | "patch" | "patch-if" | "remove" |
- * "rmdir" | "rmrfdir" | type
- *
- * 'type' is the update type (e.g. complete or partial) and when present MUST
- * be the first entry in the update manifest. The type is used to support
- * downgrades by causing the actions defined in precomplete to be performed.
- *
- * updatev3.manifest
- * -----------------
- * method = "add" | "add-if" | "add-if-not" | "patch" | "patch-if" |
- * "remove" | "rmdir" | "rmrfdir" | type
- *
- * 'add-if-not' adds a file if it doesn't exist.
- *
- * precomplete
- * -----------
- * method = "remove" | "rmdir"
- */
-#include "bspatch.h"
-#include "progressui.h"
-#include "archivereader.h"
-#include "readstrings.h"
-#include "errors.h"
-#include "bzlib.h"
-#include <thread>
-#include <vector>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <errno.h>
-#include <algorithm>
-#include <memory>
-
-#include <config_version.h>
-
-#include "updatelogging.h"
-
-#include <onlineupdate/mozilla/Compiler.h>
-#include <onlineupdate/mozilla/Types.h>
-
-#ifdef _WIN32
-#include <comphelper/windowsStart.hxx>
-#include "uachelper.h"
-#include "pathhash.h"
-
-// TODO:moggi taken from the mozilla code -- find a better solution
-#define INVALID_APPLYTO_DIR_ERROR 74
-#define REMOVE_FILE_SPEC_ERROR 71
-#define INVALID_APPLYTO_DIR_STAGED_ERROR 72
-
-#endif
-
-
-// Amount of the progress bar to use in each of the 3 update stages,
-// should total 100.0.
-#define PROGRESS_PREPARE_SIZE 20.0f
-#define PROGRESS_EXECUTE_SIZE 75.0f
-#define PROGRESS_FINISH_SIZE 5.0f
-
-// Amount of time in ms to wait for the parent process to close
-#ifdef _WIN32
-#define PARENT_WAIT 5000
-#endif
-
-#if defined(MACOSX)
-// These functions are defined in launchchild_osx.mm
-void CleanupElevatedMacUpdate(bool aFailureOccurred);
-bool IsOwnedByGroupAdmin(const char* aAppBundle);
-bool IsRecursivelyWritable(const char* aPath);
-void LaunchChild(int argc, const char** argv);
-void LaunchMacPostProcess(const char* aAppBundle);
-bool ObtainUpdaterArguments(int* argc, char*** argv);
-bool ServeElevatedUpdate(int argc, const char** argv);
-void SetGroupOwnershipAndPermissions(const char* aAppBundle);
-struct UpdateServerThreadArgs
-{
- int argc;
- const NS_tchar** argv;
-};
-#endif
-
-#ifndef SSIZE_MAX
-# define SSIZE_MAX LONG_MAX
-#endif
-
-// We want to use execv to invoke the callback executable on platforms where
-// we were launched using execv. See nsUpdateDriver.cpp.
-#if defined(UNIX) && !defined(MACOSX)
-#define USE_EXECV
-#endif
-
-#if defined(VERIFY_MAR_SIGNATURE) && !defined(_WIN32) && !defined(MACOSX)
-#include <nss.h>
-#include <nspr.h>
-#endif
-
-#ifdef _WIN32
-#ifdef MAINTENANCE_SERVICE
-#include "registrycertificates.h"
-#endif
-BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
-BOOL PathGetSiblingFilePath(LPWSTR destinationBuffer,
- LPCWSTR siblingFilePath,
- LPCWSTR newFileName);
-#include "updatehelper.h"
-
-// Closes the handle if valid and if the updater is elevated returns with the
-// return code specified. This prevents multiple launches of the callback
-// application by preventing the elevated process from launching the callback.
-#define EXIT_WHEN_ELEVATED(path, handle, retCode) \
-{ \
- if (handle != INVALID_HANDLE_VALUE) { \
- CloseHandle(handle); \
- } \
- if (_waccess(path, F_OK) == 0 && NS_tremove(path) != 0) { \
- LogFinish(); \
- return retCode; \
- } \
-}
-#endif
-
-//-----------------------------------------------------------------------------
-
-// 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.
-#if defined __GNUC__
-extern "C" __attribute__((visibility("default"))) unsigned int BZ2_crc32Table[256];
-#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-extern "C" __global unsigned int BZ2_crc32Table[256];
-#else
-extern "C" unsigned int BZ2_crc32Table[256];
-#endif
-
-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;
-}
-
-//-----------------------------------------------------------------------------
-
-// A simple stack based container for a FILE struct that closes the
-// file descriptor from its destructor.
-class AutoFile
-{
-public:
- explicit AutoFile(FILE* file = nullptr)
- : mFile(file)
- {
- }
-
- ~AutoFile()
- {
- if (mFile != nullptr)
- fclose(mFile);
- }
-
- AutoFile &operator=(FILE* file)
- {
- if (mFile != 0)
- fclose(mFile);
- mFile = file;
- return *this;
- }
-
- operator FILE*()
- {
- return mFile;
- }
-
- FILE* get()
- {
- return mFile;
- }
-
-private:
- FILE* mFile;
-};
-
-struct MARChannelStringTable
-{
- MARChannelStringTable()
- {
- MARChannelID[0] = '\0';
- }
-
- char MARChannelID[MAX_TEXT_LEN];
-};
-
-//-----------------------------------------------------------------------------
-
-static NS_tchar* gPatchDirPath;
-static NS_tchar gInstallDirPath[MAXPATHLEN];
-static NS_tchar gWorkingDirPath[MAXPATHLEN];
-static bool gSucceeded = false;
-static bool sStagedUpdate = false;
-static bool sReplaceRequest = false;
-static bool sUsingService = false;
-
-#ifdef _WIN32
-// The current working directory specified in the command line.
-static NS_tchar* gDestPath;
-static NS_tchar gCallbackRelPath[MAXPATHLEN];
-static NS_tchar gCallbackBackupPath[MAXPATHLEN];
-static NS_tchar gDeleteDirPath[MAXPATHLEN];
-#endif
-
-static const NS_tchar kWhitespace[] = NS_T(" \t");
-static const NS_tchar kNL[] = NS_T("\r\n");
-static const NS_tchar kQuote[] = NS_T("\"");
-
-static NS_tchar*
-mstrtok(const NS_tchar *delims, NS_tchar **str)
-{
- if (!*str || !**str)
- {
- *str = nullptr;
- return nullptr;
- }
-
- // skip leading "whitespace"
- NS_tchar *ret = *str;
- const NS_tchar *d;
- do
- {
- for (d = delims; *d != NS_T('\0'); ++d)
- {
- if (*ret == *d)
- {
- ++ret;
- break;
- }
- }
- }
- while (*d);
-
- if (!*ret)
- {
- *str = ret;
- return nullptr;
- }
-
- NS_tchar *i = ret;
- do
- {
- for (d = delims; *d != NS_T('\0'); ++d)
- {
- if (*i == *d)
- {
- *i = NS_T('\0');
- *str = ++i;
- return ret;
- }
- }
- ++i;
- }
- while (*i);
-
- *str = nullptr;
- return ret;
-}
-
-#if defined(_WIN32) && defined(MAINTENANCE_SERVICE)
-static bool
-EnvHasValue(const char *name)
-{
- const char *val = getenv(name);
- return (val && *val);
-}
-#endif
-
-/**
- * Converts a relative update path to an absolute path related to the working
- * or install directory. Allocates a new NS_tchar[] based path!
- *
- * @param relpath
- * The relative path to convert to a full path.
- * @return valid filesystem full path or nullptr if memory allocation fails.
- */
-static NS_tchar*
-new_absolute_path(const NS_tchar *relpath)
-{
- NS_tchar *destpath = sStagedUpdate ? gWorkingDirPath : gInstallDirPath;
- size_t lendestpath = NS_tstrlen(destpath);
- size_t lenrelpath = NS_tstrlen(relpath);
- NS_tchar *s = new NS_tchar[lendestpath + lenrelpath + 2];
-
- NS_tchar *c = s;
-
- NS_tstrcpy(c, destpath);
- c += lendestpath;
- NS_tstrcat(c, NS_T("/"));
- c++;
-
- NS_tstrcat(c, relpath);
- c += lenrelpath;
- *c = NS_T('\0');
- return s;
-}
-
-namespace {
-
-bool is_userprofile_in_instdir()
-{
- return false;
- /*
- // 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;
- */
-}
-
-}
-
-/**
- * Get a pointer in the absolute path, relative to the working or install
- * directory. Returns itself, if not absolute or outside of the directory.
- *
- * @param abs_path
- * An absolute path.
- * return pointer to the location within fullpath where the relative path starts
- * or fullpath itself if it already looks relative.
- */
-static const NS_tchar*
-get_relative_offset(const NS_tchar *abs_path)
-{
- // If the path isn't absolute, just return it as-is.
-#ifdef _WIN32
- if (abs_path[1] != ':' && abs_path[2] != '\\')
- {
-#else
- if (abs_path[0] != '/')
- {
-#endif
- return abs_path;
- }
-
- NS_tchar *prefix = sStagedUpdate ? gWorkingDirPath : gInstallDirPath;
-
- size_t len = NS_tstrlen(prefix);
- if (NS_tstrlen(abs_path) <= len)
- return abs_path;
- if (0 != NS_tstrncmp(abs_path, prefix, len))
- return abs_path;
- return abs_path + len + 1;
-}
-
-/**
- * Gets the platform specific path and performs simple checks to the path. If
- * the path checks don't pass nullptr will be returned.
- *
- * @param line
- * The line from the manifest that contains the path.
- * @param isdir
- * Whether the path is a directory path. Defaults to false.
- * @return valid filesystem path or nullptr if the path checks fail.
- */
-static NS_tchar*
-get_valid_path(NS_tchar **line, bool isdir = false)
-{
- NS_tchar *path = mstrtok(kQuote, line);
- if (!path)
- {
- LOG(("get_valid_path: unable to determine path: " LOG_S, line));
- return nullptr;
- }
-
- // All paths must be relative from the current working directory
- if (path[0] == NS_T('/'))
- {
- LOG(("get_valid_path: path must be relative: " LOG_S, path));
- return nullptr;
- }
-
-#ifdef _WIN32
- // All paths must be relative from the current working directory
- if (path[0] == NS_T('\\') || path[1] == NS_T(':'))
- {
- LOG(("get_valid_path: path must be relative: " LOG_S, path));
- return nullptr;
- }
-#endif
-
- if (isdir)
- {
- // Directory paths must have a trailing forward slash.
- if (path[NS_tstrlen(path) - 1] != NS_T('/'))
- {
- LOG(("get_valid_path: directory paths must have a trailing forward " \
- "slash: " LOG_S, path));
- return nullptr;
- }
-
- // Remove the trailing forward slash because stat on Windows will return
- // ENOENT if the path has a trailing slash.
- path[NS_tstrlen(path) - 1] = NS_T('\0');
- }
-
- // Don't allow relative paths that resolve to a parent directory.
- if (NS_tstrstr(path, NS_T("..")) != nullptr)
- {
- LOG(("get_valid_path: paths must not contain '..': " LOG_S, path));
- return nullptr;
- }
-
- return path;
-}
-
-static NS_tchar*
-get_quoted_path(const NS_tchar *path)
-{
- size_t lenQuote = NS_tstrlen(kQuote);
- size_t lenPath = NS_tstrlen(path);
- size_t len = lenQuote + lenPath + lenQuote + 1;
-
- NS_tchar *s = (NS_tchar *) malloc(len * sizeof(NS_tchar));
- if (!s)
- return nullptr;
-
- NS_tchar *c = s;
- NS_tstrcpy(c, kQuote);
- c += lenQuote;
- NS_tstrcat(c, path);
- c += lenPath;
- NS_tstrcat(c, kQuote);
- c += lenQuote;
- *c = NS_T('\0');
- c++;
- return s;
-}
-
-static void ensure_write_permissions(const NS_tchar *path)
-{
-#ifdef _WIN32
- (void) _wchmod(path, _S_IREAD | _S_IWRITE);
-#else
- struct stat fs;
- if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR))
- {
- (void)chmod(path, fs.st_mode | S_IWUSR);
- }
-#endif
-}
-
-static int ensure_remove(const NS_tchar *path)
-{
- ensure_write_permissions(path);
- int rv = NS_tremove(path);
- if (rv)
- LOG(("ensure_remove: failed to remove file: " LOG_S ", rv: %d, err: %d",
- path, rv, errno));
- return rv;
-}
-
-// Remove the directory pointed to by path and all of its files and sub-directories.
-static int ensure_remove_recursive(const NS_tchar *path,
- bool continueEnumOnFailure = false)
-{
- // We use lstat rather than stat here so that we can successfully remove
- // symlinks.
- struct NS_tstat_t sInfo;
- int rv = NS_tlstat(path, &sInfo);
- if (rv)
- {
- // This error is benign
- return rv;
- }
- if (!S_ISDIR(sInfo.st_mode))
- {
- return ensure_remove(path);
- }
-
- NS_tDIR *dir;
- NS_tdirent *entry;
-
- dir = NS_topendir(path);
- if (!dir)
- {
- LOG(("ensure_remove_recursive: unable to open directory: " LOG_S
- ", rv: %d, err: %d", path, rv, errno));
- return rv;
- }
-
- while ((entry = NS_treaddir(dir)) != 0)
- {
- if (NS_tstrcmp(entry->d_name, NS_T(".")) &&
- NS_tstrcmp(entry->d_name, NS_T("..")))
- {
- NS_tchar childPath[MAXPATHLEN];
- NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]),
- NS_T("%s/%s"), path, entry->d_name);
- rv = ensure_remove_recursive(childPath);
- if (rv && !continueEnumOnFailure)
- {
- break;
- }
- }
- }
-
- NS_tclosedir(dir);
-
- if (rv == OK)
- {
- ensure_write_permissions(path);
- rv = NS_trmdir(path);
- if (rv)
- {
- LOG(("ensure_remove_recursive: unable to remove directory: " LOG_S
- ", rv: %d, err: %d", path, rv, errno));
- }
- }
- return rv;
-}
-
-static bool is_read_only(const NS_tchar *flags)
-{
- size_t length = NS_tstrlen(flags);
- if (length == 0)
- return false;
-
- // Make sure the string begins with "r"
- if (flags[0] != NS_T('r'))
- return false;
-
- // Look for "r+" or "r+b"
- if (length > 1 && flags[1] == NS_T('+'))
- return false;
-
- // Look for "rb+"
- if (NS_tstrcmp(flags, NS_T("rb+")) == 0)
- return false;
-
- return true;
-}
-
-static FILE* ensure_open(const NS_tchar *path, const NS_tchar *flags, unsigned int options)
-{
- ensure_write_permissions(path);
- FILE* f = NS_tfopen(path, flags);
- if (is_read_only(flags))
- {
- // Don't attempt to modify the file permissions if the file is being opened
- // in read-only mode.
- return f;
- }
- if (NS_tchmod(path, options) != 0)
- {
- if (f != nullptr)
- {
- fclose(f);
- }
- return nullptr;
- }
- struct NS_tstat_t ss;
- if (NS_tstat(path, &ss) != 0 || ss.st_mode != options)
- {
- if (f != nullptr)
- {
- fclose(f);
- }
- return nullptr;
- }
- return f;
-}
-
-// Ensure that the directory containing this file exists.
-static int ensure_parent_dir(const NS_tchar *path)
-{
- int rv = OK;
-
- NS_tchar *slash = (NS_tchar *) NS_tstrrchr(path, NS_T('/'));
- if (slash)
- {
- *slash = NS_T('\0');
- rv = ensure_parent_dir(path);
- // Only attempt to create the directory if we're not at the root
- if (rv == OK && *path)
- {
- rv = NS_tmkdir(path, 0755);
- // If the directory already exists, then ignore the error.
- if (rv < 0 && errno != EEXIST)
- {
- LOG(("ensure_parent_dir: failed to create directory: " LOG_S ", " \
- "err: %d", path, errno));
- rv = WRITE_ERROR;
- }
- else
- {
- rv = OK;
- }
- }
- *slash = NS_T('/');
- }
- return rv;
-}
-
-#ifdef UNIX
-static int ensure_copy_symlink(const NS_tchar *path, const NS_tchar *dest)
-{
- // Copy symlinks by creating a new symlink to the same target
- NS_tchar target[MAXPATHLEN + 1] = {NS_T('\0')};
- int rv = readlink(path, target, MAXPATHLEN);
- if (rv == -1)
- {
- LOG(("ensure_copy_symlink: failed to read the link: " LOG_S ", err: %d",
- path, errno));
- return READ_ERROR;
- }
- rv = symlink(target, dest);
- if (rv == -1)
- {
- LOG(("ensure_copy_symlink: failed to create the new link: " LOG_S ", target: " LOG_S " err: %d",
- dest, target, errno));
- return READ_ERROR;
- }
- return 0;
-}
-#endif
-
-// Copy the file named path onto a new file named dest.
-static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
-{
-#ifdef _WIN32
- // Fast path for Windows
- bool result = CopyFileW(path, dest, false);
- if (!result)
- {
- LOG(("ensure_copy: failed to copy the file " LOG_S " over to " LOG_S ", lasterr: %x",
- path, dest, GetLastError()));
- return WRITE_ERROR_FILE_COPY;
- }
- return OK;
-#else
- struct NS_tstat_t ss;
- int rv = NS_tlstat(path, &ss);
- if (rv)
- {
- LOG(("ensure_copy: failed to read file status info: " LOG_S ", err: %d",
- path, errno));
- return READ_ERROR;
- }
-
-#ifdef UNIX
- if (S_ISLNK(ss.st_mode))
- {
- return ensure_copy_symlink(path, dest);
- }
-#endif
-
- AutoFile infile(ensure_open(path, NS_T("rb"), ss.st_mode));
- if (!infile)
- {
- LOG(("ensure_copy: failed to open the file for reading: " LOG_S ", err: %d",
- path, errno));
- return READ_ERROR;
- }
- AutoFile outfile(ensure_open(dest, NS_T("wb"), ss.st_mode));
- if (!outfile)
- {
- LOG(("ensure_copy: failed to open the file for writing: " LOG_S ", err: %d",
- dest, errno));
- return WRITE_ERROR;
- }
-
- // This block size was chosen pretty arbitrarily but seems like a reasonable
- // compromise. For example, the optimal block size on a modern macOS machine
- // is 100k */
- const int blockSize = 32 * 1024;
- void* buffer = malloc(blockSize);
- if (!buffer)
- return UPDATER_MEM_ERROR;
-
- while (!feof(infile.get()))
- {
- size_t read = fread(buffer, 1, blockSize, infile);
- if (ferror(infile.get()))
- {
- LOG(("ensure_copy: failed to read the file: " LOG_S ", err: %d",
- path, errno));
- free(buffer);
- return READ_ERROR;
- }
-
- size_t written = 0;
-
- while (written < read)
- {
- size_t nCount = read - written;
- size_t chunkWritten = fwrite(buffer, 1, nCount, outfile);
- if (chunkWritten != nCount)
- {
- LOG(("ensure_copy: failed to write the file: " LOG_S ", err: %d",
- dest, errno));
- free(buffer);
- return WRITE_ERROR_FILE_COPY;
- }
-
- written += chunkWritten;
- }
- }
-
- rv = NS_tchmod(dest, ss.st_mode);
-
- free(buffer);
- return rv;
-#endif
-}
-
-template <unsigned N>
-struct copy_recursive_skiplist
-{
- NS_tchar paths[N][MAXPATHLEN];
-
- void append(unsigned index, const NS_tchar *path, const NS_tchar *suffix)
- {
- 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)
- {
- if (!NS_tstricmp(paths[i], path))
- {
- return true;
- }
- }
- return false;
- }
-};
-
-// Copy all of the files and subdirectories under path to a new directory named dest.
-// The path names in the skiplist will be skipped and will not be copied.
-template <unsigned N>
-static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest,
- copy_recursive_skiplist<N>& skiplist)
-{
- struct NS_tstat_t sInfo;
- int rv = NS_tlstat(path, &sInfo);
- if (rv)
- {
- LOG(("ensure_copy_recursive: path doesn't exist: " LOG_S ", rv: %d, err: %d",
- path, rv, errno));
- return READ_ERROR;
- }
-
-#ifdef UNIX
- if (S_ISLNK(sInfo.st_mode))
- {
- return ensure_copy_symlink(path, dest);
- }
-#endif
-
- if (!S_ISDIR(sInfo.st_mode))
- {
- return ensure_copy(path, dest);
- }
-
- rv = NS_tmkdir(dest, sInfo.st_mode);
- if (rv < 0 && errno != EEXIST)
- {
- LOG(("ensure_copy_recursive: could not create destination directory: " LOG_S ", rv: %d, err: %d",
- path, rv, errno));
- return WRITE_ERROR;
- }
-
- NS_tDIR *dir;
- NS_tdirent *entry;
-
- dir = NS_topendir(path);
- if (!dir)
- {
- LOG(("ensure_copy_recursive: path is not a directory: " LOG_S ", rv: %d, err: %d",
- path, rv, errno));
- return READ_ERROR;
- }
-
- while ((entry = NS_treaddir(dir)) != 0)
- {
- if (NS_tstrcmp(entry->d_name, NS_T(".")) &&
- NS_tstrcmp(entry->d_name, NS_T("..")))
- {
- NS_tchar childPath[MAXPATHLEN];
- NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]),
- NS_T("%s/%s"), path, entry->d_name);
- if (skiplist.find(childPath))
- {
- continue;
- }
- NS_tchar childPathDest[MAXPATHLEN];
- NS_tsnprintf(childPathDest, sizeof(childPathDest)/sizeof(childPathDest[0]),
- NS_T("%s/%s"), dest, entry->d_name);
- rv = ensure_copy_recursive(childPath, childPathDest, skiplist);
- if (rv)
- {
- break;
- }
- }
- }
- NS_tclosedir(dir);
- return rv;
-}
-
-// Renames the specified file to the new file specified. If the destination file
-// exists it is removed.
-static int rename_file(const NS_tchar *spath, const NS_tchar *dpath,
- bool allowDirs = false)
-{
- int rv = ensure_parent_dir(dpath);
- if (rv)
- return rv;
-
- struct NS_tstat_t spathInfo;
- rv = NS_tstat(spath, &spathInfo);
- if (rv)
- {
- LOG(("rename_file: failed to read file status info: " LOG_S ", " \
- "err: %d", spath, errno));
- return READ_ERROR;
- }
-
- if (!S_ISREG(spathInfo.st_mode))
- {
- if (allowDirs && !S_ISDIR(spathInfo.st_mode))
- {
- LOG(("rename_file: path present, but not a file: " LOG_S ", err: %d",
- spath, errno));
- return RENAME_ERROR_EXPECTED_FILE;
- }
- else
- {
- LOG(("rename_file: proceeding to rename the directory"));
- }
- }
-
- if (!NS_taccess(dpath, F_OK))
- {
- if (ensure_remove(dpath))
- {
- LOG(("rename_file: destination file exists and could not be " \
- "removed: " LOG_S, dpath));
- return WRITE_ERROR_DELETE_FILE;
- }
- }
-
- if (NS_trename(spath, dpath) != 0)
- {
- LOG(("rename_file: failed to rename file - src: " LOG_S ", " \
- "dst:" LOG_S ", err: %d", spath, dpath, errno));
- return WRITE_ERROR;
- }
-
- return OK;
-}
-
-#ifdef _WIN32
-// Remove the directory pointed to by path and all of its files and
-// sub-directories. If a file is in use move it to the tobedeleted directory
-// and attempt to schedule removal of the file on reboot
-static int remove_recursive_on_reboot(const NS_tchar *path, const NS_tchar *deleteDir)
-{
- struct NS_tstat_t sInfo;
- int rv = NS_tlstat(path, &sInfo);
- if (rv)
- {
- // This error is benign
- return rv;
- }
-
- if (!S_ISDIR(sInfo.st_mode))
- {
- NS_tchar tmpDeleteFile[MAXPATHLEN];
- GetTempFileNameW(deleteDir, L"rep", 0, tmpDeleteFile);
- NS_tremove(tmpDeleteFile);
- rv = rename_file(path, tmpDeleteFile, false);
- if (MoveFileEx(rv ? path : tmpDeleteFile, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT))
- {
- LOG(("remove_recursive_on_reboot: file will be removed on OS reboot: "
- LOG_S, rv ? path : tmpDeleteFile));
- }
- else
- {
- LOG(("remove_recursive_on_reboot: failed to schedule OS reboot removal of "
- "file: " LOG_S, rv ? path : tmpDeleteFile));
- }
- return rv;
- }
-
- NS_tDIR *dir;
- NS_tdirent *entry;
-
- dir = NS_topendir(path);
- if (!dir)
- {
- LOG(("remove_recursive_on_reboot: unable to open directory: " LOG_S
- ", rv: %d, err: %d",
- path, rv, errno));
- return rv;
- }
-
- while ((entry = NS_treaddir(dir)) != 0)
- {
- if (NS_tstrcmp(entry->d_name, NS_T(".")) &&
- NS_tstrcmp(entry->d_name, NS_T("..")))
- {
- NS_tchar childPath[MAXPATHLEN];
- NS_tsnprintf(childPath, sizeof(childPath)/sizeof(childPath[0]),
- NS_T("%s/%s"), path, entry->d_name);
- // There is no need to check the return value of this call since this
- // function is only called after an update is successful and there is not
- // much that can be done to recover if it isn't successful. There is also
- // no need to log the value since it will have already been logged.
- remove_recursive_on_reboot(childPath, deleteDir);
- }
- }
-
- NS_tclosedir(dir);
-
- if (rv == OK)
- {
- ensure_write_permissions(path);
- rv = NS_trmdir(path);
- if (rv)
- {
- LOG(("remove_recursive_on_reboot: unable to remove directory: " LOG_S
- ", rv: %d, err: %d", path, rv, errno));
- }
- }
- return rv;
-}
-#endif
-
-//-----------------------------------------------------------------------------
-
-// Create a backup of the specified file by renaming it.
-static int backup_create(const NS_tchar *path)
-{
- NS_tchar backup[MAXPATHLEN];
- NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]),
- NS_T("%s") BACKUP_EXT, path);
-
- return rename_file(path, backup);
-}
-
-// Rename the backup of the specified file that was created by renaming it back
-// to the original file.
-static int backup_restore(const NS_tchar *path, const NS_tchar *relPath)
-{
- NS_tchar backup[MAXPATHLEN];
- NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]),
- NS_T("%s") BACKUP_EXT, path);
-
- NS_tchar relBackup[MAXPATHLEN];
- NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]),
- NS_T("%s") BACKUP_EXT, relPath);
-
- if (NS_taccess(backup, F_OK))
- {
- LOG(("backup_restore: backup file doesn't exist: " LOG_S, relBackup));
- return OK;
- }
-
- return rename_file(backup, path);
-}
-
-// Discard the backup of the specified file that was created by renaming it.
-static int backup_discard(const NS_tchar *path, const NS_tchar *relPath)
-{
- NS_tchar backup[MAXPATHLEN];
- NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]),
- NS_T("%s") BACKUP_EXT, path);
-
- NS_tchar relBackup[MAXPATHLEN];
- NS_tsnprintf(relBackup, sizeof(relBackup) / sizeof(relBackup[0]),
- NS_T("%s") BACKUP_EXT, relPath);
-
- // Nothing to discard
- if (NS_taccess(backup, F_OK))
- {
- return OK;
- }
-
- int rv = ensure_remove(backup);
-#if defined(_WIN32)
- if (rv && !sStagedUpdate && !sReplaceRequest)
- {
- LOG(("backup_discard: unable to remove: " LOG_S, relBackup));
- NS_tchar path[MAXPATHLEN];
- GetTempFileNameW(gDeleteDirPath, L"moz", 0, path);
- if (rename_file(backup, path))
- {
- LOG(("backup_discard: failed to rename file:" LOG_S ", dst:" LOG_S,
- relBackup, relPath));
- return WRITE_ERROR_DELETE_BACKUP;
- }
- // The MoveFileEx call to remove the file on OS reboot will fail if the
- // process doesn't have write access to the HKEY_LOCAL_MACHINE registry key
- // but this is ok since the installer / uninstaller will delete the
- // directory containing the file along with its contents after an update is
- // applied, on reinstall, and on uninstall.
- if (MoveFileEx(path, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT))
- {
- LOG(("backup_discard: file renamed and will be removed on OS " \
- "reboot: " LOG_S, relPath));
- }
- else
- {
- LOG(("backup_discard: failed to schedule OS reboot removal of " \
- "file: " LOG_S, relPath));
- }
- }
-#else
- if (rv)
- return WRITE_ERROR_DELETE_BACKUP;
-#endif
-
- return OK;
-}
-
-// Helper function for post-processing a temporary backup.
-static void backup_finish(const NS_tchar *path, const NS_tchar *relPath,
- int status)
-{
- if (status == OK)
- backup_discard(path, relPath);
- else
- backup_restore(path, relPath);
-}
-
-//-----------------------------------------------------------------------------
-
-static int DoUpdate(ArchiveReader& ArchiveReader);
-
-class Action
-{
-public:
- Action() : mProgressCost(1), mNext(nullptr) { }
- virtual ~Action() { }
-
- virtual int Parse(NS_tchar *line) = 0;
-
- // Do any preprocessing to ensure that the action can be performed. Execute
- // will be called if this Action and all others return OK from this method.
- virtual int Prepare() = 0;
-
- // Perform the operation. Return OK to indicate success. After all actions
- // have been executed, Finish will be called. A requirement of Execute is
- // that its operation be reversible from Finish.
- virtual int Execute() = 0;
-
- // Finish is called after execution of all actions. If status is OK, then
- // all actions were successfully executed. Otherwise, some action failed.
- virtual void Finish(int status) = 0;
-
- int mProgressCost;
-private:
- Action* mNext;
-
- friend class ActionList;
-};
-
-class RemoveFile : public Action
-{
-public:
- RemoveFile() : mSkip(0) { }
-
- int Parse(NS_tchar *line);
- int Prepare();
- int Execute();
- void Finish(int status);
-
-private:
- std::unique_ptr<const NS_tchar[]> mFile;
- std::unique_ptr<NS_tchar[]> mRelPath;
- int mSkip;
-};
-
-int
-RemoveFile::Parse(NS_tchar *line)
-{
- // format "<deadfile>"
-
- NS_tchar* validPath = get_valid_path(&line);
- if (!validPath)
- return PARSE_ERROR;
-
- mRelPath.reset(new NS_tchar[MAXPATHLEN]);
- NS_tstrcpy(mRelPath.get(), validPath);
-
- mFile.reset(new_absolute_path(validPath));
- if (!mFile)
- {
- return PARSE_ERROR;
- }
-
- return OK;
-}
-
-int
-RemoveFile::Prepare()
-{
- // Skip the file if it already doesn't exist.
- int rv = NS_taccess(mFile.get(), F_OK);
- if (rv)
- {
- mSkip = 1;
- mProgressCost = 0;
- return OK;
- }
-
- LOG(("PREPARE REMOVEFILE " LOG_S, mRelPath.get()));
-
- // Make sure that we're actually a file...
- struct NS_tstat_t fileInfo;
- rv = NS_tstat(mFile.get(), &fileInfo);
- if (rv)
- {
- LOG(("failed to read file status info: " LOG_S ", err: %d", mFile.get(),
- errno));
- return READ_ERROR;
- }
-
- if (!S_ISREG(fileInfo.st_mode))
- {
- LOG(("path present, but not a file: " LOG_S, mFile.get()));
- return DELETE_ERROR_EXPECTED_FILE;
- }
-
- NS_tchar *slash = (NS_tchar *) NS_tstrrchr(mFile.get(), NS_T('/'));
- if (slash)
- {
- *slash = NS_T('\0');
- rv = NS_taccess(mFile.get(), W_OK);
- *slash = NS_T('/');
- }
- else
- {
- rv = NS_taccess(NS_T("."), W_OK);
- }
-
- if (rv)
- {
- LOG(("access failed: %d", errno));
- return WRITE_ERROR_FILE_ACCESS_DENIED;
- }
-
- return OK;
-}
-
-int
-RemoveFile::Execute()
-{
- if (mSkip)
- return OK;
-
- LOG(("EXECUTE REMOVEFILE " LOG_S, mRelPath.get()));
-
- // The file is checked for existence here and in Prepare since it might have
- // been removed by a separate instruction: bug 311099.
- int rv = NS_taccess(mFile.get(), F_OK);
- if (rv)
- {
- LOG(("file cannot be removed because it does not exist; skipping"));
- mSkip = 1;
- return OK;
- }
-
- // Rename the old file. It will be removed in Finish.
- rv = backup_create(mFile.get());
- if (rv)
- {
- LOG(("backup_create failed: %d", rv));
- return rv;
- }
-
- return OK;
-}
-
-void
-RemoveFile::Finish(int status)
-{
- if (mSkip)
- return;
-
- LOG(("FINISH REMOVEFILE " LOG_S, mRelPath.get()));
-
- backup_finish(mFile.get(), mRelPath.get(), status);
-}
-
-class RemoveDir : public Action
-{
-public:
- RemoveDir() : mSkip(0) { }
-
- virtual int Parse(NS_tchar *line);
- virtual int Prepare(); // check that the source dir exists
- virtual int Execute();
- virtual void Finish(int status);
-
-private:
- std::unique_ptr<NS_tchar[]> mDir;
- std::unique_ptr<NS_tchar[]> mRelPath;
- int mSkip;
-};
-
-int
-RemoveDir::Parse(NS_tchar *line)
-{
- // format "<deaddir>/"
-
- NS_tchar* validPath = get_valid_path(&line, true);
- if (!validPath)
- return PARSE_ERROR;
-
- mRelPath.reset(new NS_tchar[MAXPATHLEN]);
- NS_tstrcpy(mRelPath.get(), validPath);
-
- mDir.reset(new_absolute_path(validPath));
- if (!mDir)
- {
- return PARSE_ERROR;
- }
-
- return OK;
-}
-
-int
-RemoveDir::Prepare()
-{
- // We expect the directory to exist if we are to remove it.
- int rv = NS_taccess(mDir.get(), F_OK);
- if (rv)
- {
- mSkip = 1;
- mProgressCost = 0;
- return OK;
- }
-
- LOG(("PREPARE REMOVEDIR " LOG_S "/", mRelPath.get()));
-
- // Make sure that we're actually a dir.
- struct NS_tstat_t dirInfo;
- rv = NS_tstat(mDir.get(), &dirInfo);
- if (rv)
- {
- LOG(("failed to read directory status info: " LOG_S ", err: %d", mRelPath.get(),
- errno));
- return READ_ERROR;
- }
-
- if (!S_ISDIR(dirInfo.st_mode))
- {
- LOG(("path present, but not a directory: " LOG_S, mRelPath.get()));
- return DELETE_ERROR_EXPECTED_DIR;
- }
-
- rv = NS_taccess(mDir.get(), W_OK);
- if (rv)
- {
- LOG(("access failed: %d, %d", rv, errno));
- return WRITE_ERROR_DIR_ACCESS_DENIED;
- }
-
- return OK;
-}
-
-int
-RemoveDir::Execute()
-{
- if (mSkip)
- return OK;
-
- LOG(("EXECUTE REMOVEDIR " LOG_S "/", mRelPath.get()));
-
- // The directory is checked for existence at every step since it might have
- // been removed by a separate instruction: bug 311099.
- int rv = NS_taccess(mDir.get(), F_OK);
- if (rv)
- {
- LOG(("directory no longer exists; skipping"));
- mSkip = 1;
- }
-
- return OK;
-}
-
-void
-RemoveDir::Finish(int status)
-{
- if (mSkip || status != OK)
- return;
-
- LOG(("FINISH REMOVEDIR " LOG_S "/", mRelPath.get()));
-
- // The directory is checked for existence at every step since it might have
- // been removed by a separate instruction: bug 311099.
- int rv = NS_taccess(mDir.get(), F_OK);
- if (rv)
- {
- LOG(("directory no longer exists; skipping"));
- return;
- }
-
-
- if (status == OK)
- {
- if (NS_trmdir(mDir.get()))
- {
- LOG(("non-fatal error removing directory: " LOG_S "/, rv: %d, err: %d",
- mRelPath.get(), rv, errno));
- }
- }
-}
-
-class AddFile : public Action
-{
-public:
- AddFile(ArchiveReader& ar) : mAdded(false), mArchiveReader(ar) { }
-
- virtual int Parse(NS_tchar *line);
- virtual int Prepare();
- virtual int Execute();
- virtual void Finish(int status);
-
-private:
- std::unique_ptr<NS_tchar[]> mFile;
- std::unique_ptr<NS_tchar[]> mRelPath;
- bool mAdded;
- ArchiveReader& mArchiveReader;
-};
-
-int
-AddFile::Parse(NS_tchar *line)
-{
- // format "<newfile>"
-
- NS_tchar* validPath = get_valid_path(&line);
- if (!validPath)
- return PARSE_ERROR;
-
- mRelPath.reset(new NS_tchar[MAXPATHLEN]);
- NS_tstrcpy(mRelPath.get(), validPath);
-
- mFile.reset(new_absolute_path(validPath));
- if (!mFile)
- {
- return PARSE_ERROR;
- }
-
- return OK;
-}
-
-int
-AddFile::Prepare()
-{
- LOG(("PREPARE ADD " LOG_S, mRelPath.get()));
-
- return OK;
-}
-
-int
-AddFile::Execute()
-{
- LOG(("EXECUTE ADD " LOG_S, mRelPath.get()));
-
- int rv;
-
- // First make sure that we can actually get rid of any existing file.
- rv = NS_taccess(mFile.get(), F_OK);
- if (rv == 0)
- {
- rv = backup_create(mFile.get());
- if (rv)
- return rv;
- }
- else
- {
- rv = ensure_parent_dir(mFile.get());
- if (rv)
- return rv;
- }
-
-#ifdef _WIN32
- char sourcefile[MAXPATHLEN];
- if (!WideCharToMultiByte(CP_UTF8, 0, mRelPath.get(), -1, sourcefile,
- MAXPATHLEN, nullptr, nullptr))
- {
- LOG(("error converting wchar to utf8: %d", GetLastError()));
- return STRING_CONVERSION_ERROR;
- }
-
- rv = mArchiveReader.ExtractFile(sourcefile, mFile.get());
-#else
- rv = mArchiveReader.ExtractFile(mRelPath.get(), mFile.get());
-#endif
- if (!rv)
- {
- mAdded = true;
- }
- return rv;
-}
-
-void
-AddFile::Finish(int status)
-{
- LOG(("FINISH ADD " LOG_S, mRelPath.get()));
- // When there is an update failure and a file has been added it is removed
- // here since there might not be a backup to replace it.
- if (status && mAdded)
- NS_tremove(mFile.get());
- backup_finish(mFile.get(), mRelPath.get(), status);
-}
-
-class PatchFile : public Action
-{
-public:
- PatchFile(ArchiveReader& ar) : mPatchFile(nullptr), mPatchIndex(-1), buf(nullptr), mArchiveReader(ar) { }
-
- virtual ~PatchFile();
-
- virtual int Parse(NS_tchar *line);
- virtual int Prepare(); // should check for patch file and for checksum here
- virtual int Execute();
- virtual void Finish(int status);
-
-private:
- int LoadSourceFile(FILE* ofile);
-
- static int sPatchIndex;
-
- const NS_tchar *mPatchFile;
- std::unique_ptr<NS_tchar> mFile;
- std::unique_ptr<NS_tchar> mFileRelPath;
- int mPatchIndex;
- MBSPatchHeader header;
- unsigned char *buf;
- NS_tchar spath[MAXPATHLEN];
- AutoFile mPatchStream;
- ArchiveReader& mArchiveReader;
-};
-
-int PatchFile::sPatchIndex = 0;
-
-PatchFile::~PatchFile()
-{
- // Make sure mPatchStream gets unlocked on Windows; the system will do that,
- // but not until some indeterminate future time, and we want determinism.
- // Normally this happens at the end of Execute, when we close the stream;
- // this call is here in case Execute errors out.
-#ifdef _WIN32
- if (mPatchStream)
- {
- UnlockFile((HANDLE)_get_osfhandle(fileno(mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1);
- }
-#endif
-
- // delete the temporary patch file
- if (spath[0])
- NS_tremove(spath);
-
- if (buf)
- free(buf);
-}
-
-int
-PatchFile::LoadSourceFile(FILE* ofile)
-{
- struct stat os;
- int rv = fstat(fileno((FILE *)ofile), &os);
- if (rv)
- {
- LOG(("LoadSourceFile: unable to stat destination file: " LOG_S ", " \
- "err: %d", mFileRelPath.get(), errno));
- return READ_ERROR;
- }
-
- if (uint32_t(os.st_size) != header.slen)
- {
- LOG(("LoadSourceFile: destination file size %d does not match expected size %d",
- uint32_t(os.st_size), header.slen));
- return LOADSOURCE_ERROR_WRONG_SIZE;
- }
-
- buf = (unsigned char *) malloc(header.slen);
- if (!buf)
- return UPDATER_MEM_ERROR;
-
- size_t r = header.slen;
- unsigned char *rb = buf;
- while (r)
- {
- const size_t count = std::min<size_t>(SSIZE_MAX, r);
- size_t c = fread(rb, 1, count, ofile);
- if (c != count)
- {
- LOG(("LoadSourceFile: error reading destination file: " LOG_S,
- mFileRelPath.get()));
- return READ_ERROR;
- }
-
- r -= c;
- rb += c;
- }
-
- // Verify that the contents of the source file correspond to what we expect.
-
- unsigned int crc = crc32(buf, header.slen);
-
- if (crc != header.scrc32)
- {
- LOG(("LoadSourceFile: destination file crc %d does not match expected " \
- "crc %d", crc, header.scrc32));
- return CRC_ERROR;
- }
-
- return OK;
-}
-
-int
-PatchFile::Parse(NS_tchar *line)
-{
- // format "<patchfile>" "<filetopatch>"
-
- // Get the path to the patch file inside of the mar
- mPatchFile = mstrtok(kQuote, &line);
- if (!mPatchFile)
- return PARSE_ERROR;
-
- // consume whitespace between args
- NS_tchar *q = mstrtok(kQuote, &line);
- if (!q)
- return PARSE_ERROR;
-
- NS_tchar* validPath = get_valid_path(&line);
- if (!validPath)
- return PARSE_ERROR;
- mFileRelPath.reset(new NS_tchar[MAXPATHLEN]);
- NS_tstrcpy(mFileRelPath.get(), validPath);
-
- mFile.reset(new_absolute_path(validPath));
- if (!mFile)
- {
- return PARSE_ERROR;
- }
-
- return OK;
-}
-
-int
-PatchFile::Prepare()
-{
- LOG(("PREPARE PATCH " LOG_S, mFileRelPath.get()));
-
- // extract the patch to a temporary file
- mPatchIndex = sPatchIndex++;
-
- int nWrittenBytes = NS_tsnprintf(spath, sizeof(spath)/sizeof(spath[0]),
- NS_T("%s/updating/%d.patch"), gWorkingDirPath, mPatchIndex);
- (void) nWrittenBytes;
-
- NS_tremove(spath);
-
- mPatchStream = NS_tfopen(spath, NS_T("wb+"));
- if (!mPatchStream)
- return WRITE_ERROR;
-
-#ifdef _WIN32
- // Lock the patch file, so it can't be messed with between
- // when we're done creating it and when we go to apply it.
- if (!LockFile((HANDLE)_get_osfhandle(fileno(mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1))
- {
- LOG(("Couldn't lock patch file: %d", GetLastError()));
- // TODO: moggi: fix the build problem with LOCK_ERROR_PATCH_FILE
- return WRITE_ERROR; //return LOCK_ERROR_PATCH_FILE;
- }
- char sourcefile[MAXPATHLEN];
- if (!WideCharToMultiByte(CP_UTF8, 0, mPatchFile, -1, sourcefile, MAXPATHLEN,
- nullptr, nullptr))
- {
- LOG(("error converting wchar to utf8: %d", GetLastError()));
- return STRING_CONVERSION_ERROR;
- }
-
- int rv = mArchiveReader.ExtractFileToStream(sourcefile, mPatchStream);
-#else
- int rv = mArchiveReader.ExtractFileToStream(mPatchFile, mPatchStream);
-#endif
-
- return rv;
-}
-
-int
-PatchFile::Execute()
-{
- LOG(("EXECUTE PATCH " LOG_S, mFileRelPath.get()));
-
- fseek(mPatchStream, 0, SEEK_SET);
-
- int rv = MBS_ReadHeader(mPatchStream, &header);
- if (rv)
- return rv;
-
- FILE *origfile = nullptr;
-#ifdef _WIN32
- if (NS_tstrcmp(mFileRelPath.get(), gCallbackRelPath) == 0)
- {
- // Read from the copy of the callback when patching since the callback can't
- // be opened for reading to prevent the application from being launched.
- origfile = NS_tfopen(gCallbackBackupPath, NS_T("rb"));
- }
- else
- {
- origfile = NS_tfopen(mFile.get(), NS_T("rb"));
- }
-#else
- origfile = NS_tfopen(mFile.get(), NS_T("rb"));
-#endif
-
- if (!origfile)
- {
- LOG(("unable to open destination file: " LOG_S ", err: %d",
- mFileRelPath.get(), errno));
- return READ_ERROR;
- }
-
- rv = LoadSourceFile(origfile);
- fclose(origfile);
- if (rv)
- {
- LOG(("LoadSourceFile failed"));
- return rv;
- }
-
- // Rename the destination file if it exists before proceeding so it can be
- // used to restore the file to its original state if there is an error.
- struct NS_tstat_t ss;
- rv = NS_tstat(mFile.get(), &ss);
- if (rv)
- {
- LOG(("failed to read file status info: " LOG_S ", err: %d",
- mFileRelPath.get(), errno));
- return READ_ERROR;
- }
-
- rv = backup_create(mFile.get());
- if (rv)
- return rv;
-
-#if defined(HAVE_POSIX_FALLOCATE)
- AutoFile ofile(ensure_open(mFile.get(), NS_T("wb+"), ss.st_mode));
- posix_fallocate(fileno((FILE *)ofile), 0, header.dlen);
-#elif defined(_WIN32)
- bool shouldTruncate = true;
- // Creating the file, setting the size, and then closing the file handle
- // lessens fragmentation more than any other method tested. Other methods that
- // have been tested are:
- // 1. _chsize / _chsize_s reduced fragmentation though not completely.
- // 2. _get_osfhandle and then setting the size reduced fragmentation though
- // not completely. There are also reports of _get_osfhandle failing on
- // mingw.
- HANDLE hfile = CreateFileW(mFile.get(),
- GENERIC_WRITE,
- 0,
- nullptr,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- nullptr);
-
- if (hfile != INVALID_HANDLE_VALUE)
- {
- if (SetFilePointer(hfile, header.dlen,
- nullptr, FILE_BEGIN) != INVALID_SET_FILE_POINTER &&
- SetEndOfFile(hfile) != 0)
- {
- shouldTruncate = false;
- }
- CloseHandle(hfile);
- }
-
- AutoFile ofile(ensure_open(mFile.get(), shouldTruncate ? NS_T("wb+") : NS_T("rb+"),
- ss.st_mode));
-#elif defined(MACOSX)
- AutoFile ofile(ensure_open(mFile.get(), NS_T("wb+"), ss.st_mode));
- // Modified code from FileUtils.cpp
- fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, header.dlen};
- // Try to get a continuous chunk of disk space
- rv = fcntl(fileno((FILE *)ofile), F_PREALLOCATE, &store);
- if (rv == -1)
- {
- // OK, perhaps we are too fragmented, allocate non-continuous
- store.fst_flags = F_ALLOCATEALL;
- rv = fcntl(fileno((FILE *)ofile), F_PREALLOCATE, &store);
- }
-
- if (rv != -1)
- {
- ftruncate(fileno((FILE *)ofile), header.dlen);
- }
-#else
- AutoFile ofile(ensure_open(mFile.get(), NS_T("wb+"), ss.st_mode));
-#endif
-
- if (ofile == nullptr)
- {
- LOG(("unable to create new file: " LOG_S ", err: %d", mFileRelPath.get(),
- errno));
- return WRITE_ERROR_OPEN_PATCH_FILE;
- }
-
-#ifdef _WIN32
- if (!shouldTruncate)
- {
- fseek(ofile, 0, SEEK_SET);
- }
-#endif
-
- rv = MBS_ApplyPatch(&header, mPatchStream, buf, ofile);
-
- // Go ahead and do a bit of cleanup now to minimize runtime overhead.
- // Make sure mPatchStream gets unlocked on Windows; the system will do that,
- // but not until some indeterminate future time, and we want determinism.
-#ifdef _WIN32
- UnlockFile((HANDLE)_get_osfhandle(fileno(mPatchStream)), (DWORD)0, (DWORD)0, (DWORD)-1, (DWORD)-1);
-#endif
- // Set mPatchStream to nullptr to make AutoFile close the file,
- // so it can be deleted on Windows.
- mPatchStream = nullptr;
- NS_tremove(spath);
- spath[0] = NS_T('\0');
- free(buf);
- buf = nullptr;
- return rv;
-}
-
-void
-PatchFile::Finish(int status)
-{
- LOG(("FINISH PATCH " LOG_S, mFileRelPath.get()));
-
- backup_finish(mFile.get(), mFileRelPath.get(), status);
-}
-
-class AddIfFile : public AddFile
-{
-public:
- AddIfFile(ArchiveReader& archiveReader);
-
- virtual int Parse(NS_tchar *line);
- virtual int Prepare();
- virtual int Execute();
- virtual void Finish(int status);
-
-protected:
- std::unique_ptr<NS_tchar[]> mTestFile;
-};
-
-AddIfFile::AddIfFile(ArchiveReader& archiveReader):
- AddFile(archiveReader)
-{
-}
-
-int
-AddIfFile::Parse(NS_tchar *line)
-{
- // format "<testfile>" "<newfile>"
-
- mTestFile.reset(new_absolute_path(get_valid_path(&line)));
- if (!mTestFile)
- return PARSE_ERROR;
-
- // consume whitespace between args
- NS_tchar *q = mstrtok(kQuote, &line);
- if (!q)
- return PARSE_ERROR;
-
- return AddFile::Parse(line);
-}
-
-int
-AddIfFile::Prepare()
-{
- // If the test file does not exist, then skip this action.
- if (NS_taccess(mTestFile.get(), F_OK))
- {
- mTestFile = nullptr;
- return OK;
- }
-
- return AddFile::Prepare();
-}
-
-int
-AddIfFile::Execute()
-{
- if (!mTestFile)
- return OK;
-
- return AddFile::Execute();
-}
-
-void
-AddIfFile::Finish(int status)
-{
- if (!mTestFile)
- return;
-
- AddFile::Finish(status);
-}
-
-class AddIfNotFile : public AddFile
-{
-public:
- AddIfNotFile(ArchiveReader& archiveReader);
-
- virtual int Parse(NS_tchar *line);
- virtual int Prepare();
- virtual int Execute();
- virtual void Finish(int status);
-
-protected:
- std::unique_ptr<NS_tchar[]> mTestFile;
-};
-
-AddIfNotFile::AddIfNotFile(ArchiveReader& archiveReader):
- AddFile(archiveReader)
-{
-}
-
-int
-AddIfNotFile::Parse(NS_tchar *line)
-{
- // format "<testfile>" "<newfile>"
-
- mTestFile.reset(new_absolute_path(get_valid_path(&line)));
- if (!mTestFile)
- return PARSE_ERROR;
-
- // consume whitespace between args
- NS_tchar *q = mstrtok(kQuote, &line);
- if (!q)
- return PARSE_ERROR;
-
- return AddFile::Parse(line);
-}
-
-int
-AddIfNotFile::Prepare()
-{
- // If the test file exists, then skip this action.
- if (!NS_taccess(mTestFile.get(), F_OK))
- {
- mTestFile = NULL;
- return OK;
- }
-
- return AddFile::Prepare();
-}
-
-int
-AddIfNotFile::Execute()
-{
- if (!mTestFile)
- return OK;
-
- return AddFile::Execute();
-}
-
-void
-AddIfNotFile::Finish(int status)
-{
- if (!mTestFile)
- return;
-
- AddFile::Finish(status);
-}
-
-class PatchIfFile : public PatchFile
-{
-public:
- PatchIfFile(ArchiveReader& archiveReader);
-
- virtual int Parse(NS_tchar *line);
- virtual int Prepare(); // should check for patch file and for checksum here
- virtual int Execute();
- virtual void Finish(int status);
-
-private:
- std::unique_ptr<NS_tchar[]> mTestFile;
-};
-
-PatchIfFile::PatchIfFile(ArchiveReader& archiveReader):
- PatchFile(archiveReader)
-{
-}
-
-int
-PatchIfFile::Parse(NS_tchar *line)
-{
- // format "<testfile>" "<patchfile>" "<filetopatch>"
-
- mTestFile.reset(new_absolute_path(get_valid_path(&line)));
- if (!mTestFile)
- return PARSE_ERROR;
-
- // consume whitespace between args
- NS_tchar *q = mstrtok(kQuote, &line);
- if (!q)
- return PARSE_ERROR;
-
- return PatchFile::Parse(line);
-}
-
-int
-PatchIfFile::Prepare()
-{
- // If the test file does not exist, then skip this action.
- if (NS_taccess(mTestFile.get(), F_OK))
- {
- mTestFile = nullptr;
- return OK;
- }
-
- return PatchFile::Prepare();
-}
-
-int
-PatchIfFile::Execute()
-{
- if (!mTestFile)
- return OK;
-
- return PatchFile::Execute();
-}
-
-void
-PatchIfFile::Finish(int status)
-{
- if (!mTestFile)
- return;
-
- PatchFile::Finish(status);
-}
-
-//-----------------------------------------------------------------------------
-
-#ifdef _WIN32
-
-/**
- * Launch the post update application (helper.exe). It takes in the path of the
- * callback application to calculate the path of helper.exe. For service updates
- * this is called from both the system account and the current user account.
- *
- * @param installationDir The path to the callback application binary.
- * @param updateInfoDir The directory where update info is stored.
- * @return true if there was no error starting the process.
- */
-bool
-LaunchWinPostProcess(const WCHAR *installationDir,
- const WCHAR *updateInfoDir)
-{
- WCHAR workingDirectory[MAX_PATH + 1] = { L'\0' };
- wcsncpy(workingDirectory, installationDir, MAX_PATH);
-
- // TODO: moggi: needs adaptation for LibreOffice
- // Most likely we don't have the helper method yet. Check if we really need it.
-
- // Launch helper.exe to perform post processing (e.g. registry and log file
- // modifications) for the update.
- WCHAR inifile[MAX_PATH + 1] = { L'\0' };
- wcsncpy(inifile, installationDir, MAX_PATH);
- if (!PathAppendSafe(inifile, L"updater.ini"))
- {
- return false;
- }
-
- WCHAR exefile[MAX_PATH + 1];
- WCHAR exearg[MAX_PATH + 1];
- WCHAR exeasync[10];
- bool async = true;
- if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", nullptr,
- exefile, MAX_PATH + 1, inifile))
- {
- return false;
- }
-
- if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", nullptr, exearg,
- MAX_PATH + 1, inifile))
- {
- return false;
- }
-
- if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeAsync", L"TRUE",
- exeasync,
- sizeof(exeasync)/sizeof(exeasync[0]),
- inifile))
- {
- return false;
- }
-
- // Verify that exeFile doesn't contain relative paths
- if (wcsstr(exefile, L"..") != nullptr)
- {
- return false;
- }
-
- WCHAR exefullpath[MAX_PATH + 1] = { L'\0' };
- wcsncpy(exefullpath, installationDir, MAX_PATH);
- if (!PathAppendSafe(exefullpath, exefile))
- {
- return false;
- }
-
-#if !defined(TEST_UPDATER) && defined(MAINTENANCE_SERVICE)
- if (sUsingService &&
- !DoesBinaryMatchAllowedCertificates(installationDir, exefullpath))
- {
- return false;
- }
-#endif
-
- WCHAR dlogFile[MAX_PATH + 1];
- if (!PathGetSiblingFilePath(dlogFile, exefullpath, L"uninstall.update"))
- {
- return false;
- }
-
- WCHAR slogFile[MAX_PATH + 1] = { L'\0' };
- wcsncpy(slogFile, updateInfoDir, MAX_PATH);
- if (!PathAppendSafe(slogFile, L"update.log"))
- {
- return false;
- }
-
- WCHAR dummyArg[14] = { L'\0' };
- wcsncpy(dummyArg, L"argv0ignored ", sizeof(dummyArg) / sizeof(dummyArg[0]) - 1);
-
- size_t len = wcslen(exearg) + wcslen(dummyArg);
- WCHAR *cmdline = (WCHAR *) malloc((len + 1) * sizeof(WCHAR));
- if (!cmdline)
- {
- return false;
- }
-
- wcsncpy(cmdline, dummyArg, len);
- wcscat(cmdline, exearg);
-
- if (sUsingService ||
- !_wcsnicmp(exeasync, L"false", 6) ||
- !_wcsnicmp(exeasync, L"0", 2))
- {
- async = false;
- }
-
- // We want to launch the post update helper app to update the Windows
- // registry even if there is a failure with removing the uninstall.update
- // file or copying the update.log file.
- CopyFileW(slogFile, dlogFile, false);
-
- STARTUPINFOW si = {sizeof(si), 0};
- si.lpDesktop = L"";
- PROCESS_INFORMATION pi = {0};
-
- bool ok = CreateProcessW(exefullpath,
- cmdline,
- nullptr, // no special security attributes
- nullptr, // no special thread attributes
- false, // don't inherit filehandles
- 0, // No special process creation flags
- nullptr, // inherit my environment
- workingDirectory,
- &si,
- &pi);
- free(cmdline);
- if (ok)
- {
- if (!async)
- {
- WaitForSingleObject(pi.hProcess, INFINITE);
- }
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- }
- return ok;
-}
-
-#endif
-
-static void
-LaunchCallbackApp(const NS_tchar *workingDir,
- int argc,
- NS_tchar **argv,
- bool usingService)
-{
- putenv(const_cast<char*>("NO_EM_RESTART="));
- putenv(const_cast<char*>("MOZ_LAUNCHED_CHILD=1"));
-
- // Run from the specified working directory (see bug 312360). This is not
- // necessary on Windows CE since the application that launches the updater
- // passes the working directory as an --environ: command line argument.
- if (NS_tchdir(workingDir) != 0)
- {
- LOG(("Warning: chdir failed"));
- }
-
-#if defined(USE_EXECV)
- (void) argc;
- (void) usingService; // avoid warnings
- execv(argv[0], argv);
-#elif defined(MACOSX)
- LaunchChild(argc, (const char**)argv);
-#elif defined(_WIN32)
- // Do not allow the callback to run when running an update through the
- // service as session 0. The unelevated updater.exe will do the launching.
- if (!usingService)
- {
- WinLaunchChild(argv[0], argc, argv, nullptr);
- }
-#else
-# warning "Need implementation of LaunchCallbackApp"
-#endif
-}
-
-static bool
-WriteStatusFile(const char* aStatus)
-{
- NS_tchar filename[MAXPATHLEN] = {NS_T('\0')};
-#if defined(_WIN32)
- // The temp file is not removed on failure since there is client code that
- // will remove it.
- GetTempFileNameW(gPatchDirPath, L"sta", 0, filename);
-#else
- NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
- NS_T("%s/update.status"), gPatchDirPath);
-#endif
-
- // Make sure that the directory for the update status file exists
- if (ensure_parent_dir(filename))
- return false;
-
- // This is scoped to make the AutoFile close the file so it is possible to
- // move the temp file to the update.status file on Windows.
- {
- AutoFile file(NS_tfopen(filename, NS_T("wb+")));
- if (file == nullptr)
- {
- return false;
- }
-
- if (fwrite(aStatus, strlen(aStatus), 1, file) != 1)
- {
- return false;
- }
- }
-
-#if defined(_WIN32)
- NS_tchar dstfilename[MAXPATHLEN] = {NS_T('\0')};
- NS_tsnprintf(dstfilename, sizeof(dstfilename)/sizeof(dstfilename[0]),
- NS_T("%s\\update.status"), gPatchDirPath);
- if (MoveFileExW(filename, dstfilename, MOVEFILE_REPLACE_EXISTING) == 0)
- {
- return false;
- }
-#endif
-
- return true;
-}
-
-static void
-WriteStatusFile(int status)
-{
- const char *text;
-
- char buf[32];
- if (status == OK)
- {
- if (sStagedUpdate)
- {
- text = "applied\n";
- }
- else
- {
- text = "succeeded\n";
- }
- }
- else
- {
- snprintf(buf, sizeof(buf)/sizeof(buf[0]), "failed: %d\n", status);
- text = buf;
- }
-
- WriteStatusFile(text);
-}
-
-#ifdef MAINTENANCE_SERVICE
-/*
- * Read the update.status file and sets isPendingService to true if
- * the status is set to pending-service.
- *
- * @param isPendingService Out parameter for specifying if the status
- * is set to pending-service or not.
- * @return true if the information was retrieved and it is pending
- * or pending-service.
- */
-static bool
-IsUpdateStatusPendingService()
-{
- NS_tchar filename[MAXPATHLEN];
- NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
- NS_T("%s/update.status"), gPatchDirPath);
-
- AutoFile file(NS_tfopen(filename, NS_T("rb")));
- if (file == nullptr)
- return false;
-
- char buf[32] = { 0 };
- fread(buf, sizeof(buf), 1, file);
-
- const char kPendingService[] = "pending-service";
- const char kAppliedService[] = "applied-service";
-
- return (strncmp(buf, kPendingService,
- sizeof(kPendingService) - 1) == 0) ||
- (strncmp(buf, kAppliedService,
- sizeof(kAppliedService) - 1) == 0);
-}
-#endif
-
-#ifdef _WIN32
-/*
- * Read the update.status file and sets isSuccess to true if
- * the status is set to succeeded.
- *
- * @param isSucceeded Out parameter for specifying if the status
- * is set to succeeded or not.
- * @return true if the information was retrieved and it is succeeded.
- */
-static bool
-IsUpdateStatusSucceeded(bool &isSucceeded)
-{
- isSucceeded = false;
- NS_tchar filename[MAXPATHLEN];
- NS_tsnprintf(filename, sizeof(filename)/sizeof(filename[0]),
- NS_T("%s/update.status"), gPatchDirPath);
-
- AutoFile file(NS_tfopen(filename, NS_T("rb")));
- if (file == nullptr)
- return false;
-
- char buf[32] = { 0 };
- fread(buf, sizeof(buf), 1, file);
-
- const char kSucceeded[] = "succeeded";
- isSucceeded = strncmp(buf, kSucceeded,
- sizeof(kSucceeded) - 1) == 0;
- return true;
-}
-#endif
-
-/*
- * Copy the entire contents of the application installation directory to the
- * destination directory for the update process.
- *
- * @return 0 if successful, an error code otherwise.
- */
-static int
-CopyInstallDirToDestDir()
-{
- // These files should not be copied over to the updated app
-#ifdef _WIN32
-#define SKIPLIST_COUNT 4
-#elif defined(MACOSX)
-#define SKIPLIST_COUNT 1
-#else
-#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(1, gInstallDirPath, NS_T("updated"));
- skiplist.append(2, gInstallDirPath, NS_T("updates/0"));
-#ifdef _WIN32
- skiplist.append(4, gInstallDirPath, NS_T("updated.update_in_progress.lock"));
-#endif
-#endif
-
- return ensure_copy_recursive(gInstallDirPath, gWorkingDirPath, skiplist);
-}
-
-/*
- * Replace the application installation directory with the destination
- * directory in order to finish a staged update task
- *
- * @return 0 if successful, an error code otherwise.
- */
-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.
- // 3. Delete tmpDir (or defer it to the next reboot).
-
-#ifdef MACOSX
- NS_tchar destDir[MAXPATHLEN];
- NS_tsnprintf(destDir, sizeof(destDir)/sizeof(destDir[0]),
- NS_T("%s/Contents"), gInstallDirPath);
-#elif defined(_WIN32)
- // Windows preserves the case of the file/directory names. We use the
- // GetLongPathName API in order to get the correct case for the directory
- // name, so that if the user has used a different case when launching the
- // application, the installation directory's name does not change.
- NS_tchar destDir[MAXPATHLEN];
- if (!GetLongPathNameW(gInstallDirPath, destDir,
- sizeof(destDir)/sizeof(destDir[0])))
- {
- return NO_INSTALLDIR_ERROR;
- }
-#else
- NS_tchar* destDir = gInstallDirPath;
-#endif
-
- NS_tchar tmpDir[MAXPATHLEN];
- NS_tsnprintf(tmpDir, sizeof(tmpDir)/sizeof(tmpDir[0]),
- NS_T("%s.bak"), destDir);
-
- // First try to remove the possibly existing temp directory, because if this
- // directory exists, we will fail to rename destDir.
- // No need to error check here because if this fails, we will fail in the
- // next step anyways.
- ensure_remove_recursive(tmpDir);
-
- LOG(("Begin moving destDir (" LOG_S ") to tmpDir (" LOG_S ")",
- destDir, tmpDir));
- LogFlush();
- int rv = rename_file(destDir, tmpDir, true);
-#ifdef _WIN32
- // On Windows, if Firefox is launched using the shortcut, it will hold a handle
- // to its installation directory open, which might not get released in time.
- // Therefore we wait a little bit here to see if the handle is released.
- // If it's not released, we just fail to perform the replace request.
- const int max_retries = 10;
- int retries = 0;
- while (rv == WRITE_ERROR && (retries++ < max_retries))
- {
- LOG(("PerformReplaceRequest: destDir rename attempt %d failed. " \
- "File: " LOG_S ". Last error: %d, err: %d", retries,
- destDir, GetLastError(), rv));
-
- Sleep(100);
-
- rv = rename_file(destDir, tmpDir, true);
- }
-#endif
- if (rv)
- {
- // The status file will have 'pending' written to it so there is no value in
- // returning an error specific for this failure.
- LOG(("Moving destDir to tmpDir failed, err: %d", rv));
- return rv;
- }
-
- NS_tchar newDir[MAXPATHLEN];
- if (is_userprofile_in_instdir())
- {
- LOG(("user profile in instdir"));
- NS_tstrcpy(newDir, tmpDir);
- NS_tstrcat(newDir, gWorkingDirPath + NS_tstrlen(gInstallDirPath));
- LOG((LOG_S, newDir));
- }
- else
- {
- NS_tsnprintf(newDir, sizeof(newDir)/sizeof(newDir[0]),
- NS_T("%s"),
- gWorkingDirPath);
- }
-
- LOG(("Begin moving newDir (" LOG_S ") to destDir (" LOG_S ")",
- newDir, destDir));
- rv = rename_file(newDir, destDir, true);
-#ifdef MACOSX
- if (rv)
- {
- LOG(("Moving failed. Begin copying newDir (" LOG_S ") to destDir (" LOG_S ")",
- newDir, destDir));
- copy_recursive_skiplist<0> skiplist;
- rv = ensure_copy_recursive(newDir, destDir, skiplist);
- }
-#endif
- if (rv)
- {
- LOG(("Moving newDir to destDir failed, err: %d", rv));
- LOG(("Now, try to move tmpDir back to destDir"));
- ensure_remove_recursive(destDir);
- int rv2 = rename_file(tmpDir, destDir, true);
- if (rv2)
- {
- LOG(("Moving tmpDir back to destDir failed, err: %d", rv2));
- }
- // The status file will be have 'pending' written to it so there is no value
- // in returning an error specific for this failure.
- 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);
- 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 (slash)
- *slash = NS_T('/');
- }
-
-#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
- // old installation directory to the new installation directory.
- NS_tchar tmpLog[MAXPATHLEN];
- int nWrittenBytes = NS_tsnprintf(tmpLog, sizeof(tmpLog)/sizeof(tmpLog[0]),
- NS_T("%s/updates/last-update.log"), tmpDir);
- (void) nWrittenBytes;
- if (!NS_taccess(tmpLog, F_OK))
- {
- NS_tchar destLog[MAXPATHLEN];
- NS_tsnprintf(destLog, sizeof(destLog)/sizeof(destLog[0]),
- NS_T("%s/updates/last-update.log"), destDir);
- NS_tremove(destLog);
- NS_trename(tmpLog, destLog);
- }
-#endif
-
- LOG(("Now, remove the tmpDir"));
- rv = ensure_remove_recursive(tmpDir, true);
- if (rv)
- {
- LOG(("Removing tmpDir failed, err: %d", rv));
-#ifdef _WIN32
- NS_tchar deleteDir[MAXPATHLEN];
- NS_tsnprintf(deleteDir, sizeof(deleteDir)/sizeof(deleteDir[0]),
- NS_T("%s\\%s"), destDir, DELETE_DIR);
- // Attempt to remove the tobedeleted directory and then recreate it if it
- // was successfully removed.
- _wrmdir(deleteDir);
- if (NS_taccess(deleteDir, F_OK))
- {
- NS_tmkdir(deleteDir, 0755);
- }
- remove_recursive_on_reboot(tmpDir, deleteDir);
-#endif
- }
-
-#ifdef MACOSX
- // On macOS, we need to remove the staging directory after its Contents
- // directory has been moved.
- NS_tchar updatedAppDir[MAXPATHLEN];
- NS_tsnprintf(updatedAppDir, sizeof(updatedAppDir)/sizeof(updatedAppDir[0]),
- NS_T("%s/Updated.app"), gPatchDirPath);
- ensure_remove_recursive(updatedAppDir);
-#endif
-
- gSucceeded = true;
-
- return 0;
-}
-
-#ifdef _WIN32
-static void
-WaitForServiceFinishThread(void* /*param*/)
-{
- // We wait at most 10 minutes, we already waited 5 seconds previously
- // before deciding to show this UI.
- WaitForServiceStop(SVC_NAME, 595);
- QuitProgressUI();
-}
-#endif
-
-#ifdef VERIFY_MAR_SIGNATURE
-/**
- * This function reads in the ACCEPTED_MAR_CHANNEL_IDS from update-settings.ini
- *
- * @param path The path to the ini file that is to be read
- * @param results A pointer to the location to store the read strings
- * @return OK on success
- */
-static int
-ReadMARChannelIDs(const NS_tchar *path, MARChannelStringTable *results)
-{
- // TODO: moggi: needs adaptation for LibreOffice
- // Check where this function gets its parameters from
- const unsigned int kNumStrings = 1;
- const char *kUpdaterKeys = "ACCEPTED_MAR_CHANNEL_IDS\0";
- char updater_strings[kNumStrings][MAX_TEXT_LEN];
-
- int result = ReadStrings(path, kUpdaterKeys, kNumStrings,
- updater_strings, "Settings");
-
- strncpy(results->MARChannelID, updater_strings[0], MAX_TEXT_LEN - 1);
- results->MARChannelID[MAX_TEXT_LEN - 1] = 0;
-
- return result;
-}
-#endif
-
-static int
-GetUpdateFileNames(std::vector<tstring>& fileNames)
-{
- NS_tchar fileName[MAXPATHLEN];
- NS_tsnprintf(fileName, MAXPATHLEN,
- NS_T("%s/update.mar"), gPatchDirPath);
- fileNames.push_back(fileName);
-
- // add the language packs
- NS_tDIR* dir = NS_topendir(gPatchDirPath);
- if (!dir)
- {
- LOG(("Could not open directory " LOG_S, gPatchDirPath));
- return READ_ERROR;
- }
-
- NS_tdirent* entry;
- while ((entry = NS_treaddir(dir)) != nullptr)
- {
- if (NS_tstrcmp(entry->d_name, NS_T(".")) &&
- NS_tstrcmp(entry->d_name, NS_T("..")) &&
- NS_tstrcmp(entry->d_name, NS_T("update.mar")))
- {
- if (NS_tstrncmp(entry->d_name, NS_T("update"), 6) == 0)
- {
- NS_tchar *dot = NS_tstrrchr(entry->d_name, NS_T('.'));
- if (dot && !NS_tstrcmp(dot, NS_T(".mar")))
- {
- NS_tchar updatePath[MAXPATHLEN];
- NS_tsnprintf(updatePath, sizeof(updatePath)/sizeof(updatePath[0]),
- NS_T("%s/%s"), gPatchDirPath, entry->d_name);
-
- LOG (("Found language update file: " LOG_S, updatePath));
- fileNames.push_back(updatePath);
- }
- }
- }
- }
- return OK;
-}
-
-static int
-CheckSignature(ArchiveReader& archiveReader)
-{
-#ifdef VERIFY_MAR_SIGNATURE
-#ifdef _WIN32
- HKEY baseKey = nullptr;
- wchar_t valueName[] = L"Image Path";
- wchar_t rasenh[] = L"rsaenh.dll";
- bool reset = false;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- L"SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Enhanced Cryptographic Provider v1.0",
- 0, KEY_READ | KEY_WRITE,
- &baseKey) == ERROR_SUCCESS)
- {
- wchar_t path[MAX_PATH + 1];
- DWORD size = sizeof(path);
- DWORD type;
- if (RegQueryValueExW(baseKey, valueName, 0, &type,
- (LPBYTE)path, &size) == ERROR_SUCCESS)
- {
- if (type == REG_SZ && wcscmp(path, rasenh) == 0)
- {
- wchar_t rasenhFullPath[] = L"%SystemRoot%\\System32\\rsaenh.dll";
- if (RegSetValueExW(baseKey, valueName, 0, REG_SZ,
- (const BYTE*)rasenhFullPath,
- sizeof(rasenhFullPath)) == ERROR_SUCCESS)
- {
- reset = true;
- }
- }
- }
- }
-#endif
- int rv = archiveReader.VerifySignature();
-#ifdef _WIN32
- if (baseKey)
- {
- if (reset)
- {
- RegSetValueExW(baseKey, valueName, 0, REG_SZ,
- (const BYTE*)rasenh,
- sizeof(rasenh));
- }
- RegCloseKey(baseKey);
- }
-#endif
-
-
- if (rv == OK)
- {
- if (rv == OK)
- {
- NS_tchar updateSettingsPath[MAX_TEXT_LEN];
-
- // TODO: moggi: needs adaptation for LibreOffice
- // These paths need to be adapted for us.
- int nWrittenBytes = NS_tsnprintf(updateSettingsPath,
- sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]),
-#ifdef MACOSX
- NS_T("%s/Contents/Resources/update-settings.ini"),
-#else
- NS_T("%s/update-settings.ini"),
-#endif
- gWorkingDirPath);
- (void) nWrittenBytes;
- MARChannelStringTable MARStrings;
- if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK)
- {
- // If we can't read from update-settings.ini then we shouldn't impose
- // a MAR restriction. Some installations won't even include this file.
- MARStrings.MARChannelID[0] = '\0';
- }
-
- rv = archiveReader.VerifyProductInformation(MARStrings.MARChannelID,
- LIBO_VERSION_DOTTED);
- }
- }
-#endif
-
- return rv;
-}
-
-static void
-UpdateThreadFunc(void * /*param*/)
-{
- // open ZIP archive and process...
- int rv = OK;
- if (sReplaceRequest)
- {
- rv = ProcessReplaceRequest();
- }
- else
- {
- std::vector<tstring> fileNames;
- GetUpdateFileNames(fileNames);
-
- for (auto& fileName: fileNames)
- {
- ArchiveReader archiveReader;
- rv = archiveReader.Open(fileName.c_str());
- if (rv != OK)
- {
- LOG(("Could not open " LOG_S, fileName.c_str()));
- break;
- }
-
- rv = CheckSignature(archiveReader);
- if (rv != OK)
- {
- LOG(("Could not verify the signature of " LOG_S, fileName.c_str()));
- break;
- }
- }
-
- if (rv == OK && sStagedUpdate)
- {
- rv = CopyInstallDirToDestDir();
- }
-
- if (rv == OK)
- {
- for (auto& fileName: fileNames)
- {
- ArchiveReader archiveReader;
- archiveReader.Open(fileName.c_str());
- rv = DoUpdate(archiveReader);
- }
- NS_tchar updatingDir[MAXPATHLEN];
- int nWrittenBytes = NS_tsnprintf(updatingDir, sizeof(updatingDir)/sizeof(updatingDir[0]),
- NS_T("%s/updating"), gWorkingDirPath);
- (void) nWrittenBytes;
- ensure_remove_recursive(updatingDir);
- }
- }
-
- if (rv && (sReplaceRequest || sStagedUpdate))
- {
-#ifdef _WIN32
- // On Windows, the current working directory of the process should be changed
- // so that it's not locked.
- if (sStagedUpdate)
- {
- NS_tchar sysDir[MAX_PATH + 1] = { L'\0' };
- if (GetSystemDirectoryW(sysDir, MAX_PATH + 1))
- {
- NS_tchdir(sysDir);
- }
- }
-#endif
- ensure_remove_recursive(gWorkingDirPath);
- // When attempting to replace the application, we should fall back
- // to non-staged updates in case of a failure. We do this by
- // setting the status to pending, exiting the updater, and
- // launching the callback application. The callback application's
- // startup path will see the pending status, and will start the
- // updater application again in order to apply the update without
- // staging.
- if (sReplaceRequest)
- {
- WriteStatusFile(sUsingService ? "pending-service" : "pending");
- }
- else
- {
- WriteStatusFile(rv);
- }
-#ifdef TEST_UPDATER
- // Some tests need to use --test-process-updates again.
- putenv(const_cast<char*>("MOZ_TEST_PROCESS_UPDATES="));
-#endif
- }
- else
- {
- if (rv)
- {
- LOG(("failed: %d", rv));
- }
- else
- {
-#ifdef MACOSX
- // If the update was successful we need to update the timestamp on the
- // top-level macOS bundle directory so that macOS's Launch Services
- // picks up any major changes when the bundle is updated.
- if (!sStagedUpdate && utimes(gInstallDirPath, nullptr) != 0)
- {
- LOG(("Couldn't set access/modification time on application bundle."));
- }
-#endif
-
- LOG(("succeeded"));
- }
- WriteStatusFile(rv);
- }
-
- LOG(("calling QuitProgressUI"));
- QuitProgressUI();
-}
-
-#ifdef MACOSX
-static void
-ServeElevatedUpdateThreadFunc(void* param)
-{
- UpdateServerThreadArgs* threadArgs = (UpdateServerThreadArgs*)param;
- gSucceeded = ServeElevatedUpdate(threadArgs->argc, threadArgs->argv);
- if (!gSucceeded)
- {
- WriteStatusFile(ELEVATION_CANCELED);
- }
- QuitProgressUI();
-}
-
-void freeArguments(int argc, char** argv)
-{
- for (int i = 0; i < argc; i++)
- {
- free(argv[i]);
- }
- free(argv);
-}
-#endif
-
-int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv,
- int callbackIndex
-#ifdef _WIN32
- , const WCHAR* elevatedLockFilePath
- , HANDLE updateLockFileHandle
-#elif defined(MACOSX)
- , bool isElevated
-#endif
- )
-{
- if (argc > callbackIndex)
- {
-#if defined(_WIN32)
- if (gSucceeded)
- {
- if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath))
- {
- fprintf(stderr, "The post update process was not launched");
- }
-
- // The service update will only be executed if it is already installed.
- // For first time installs of the service, the install will happen from
- // the PostUpdate process. We do the service update process here
- // because it's possible we are updating with updater.exe without the
- // service if the service failed to apply the update. We want to update
- // the service to a newer version in that case. If we are not running
- // through the service, then USING_SERVICE will not exist.
- if (!sUsingService)
- {
- StartServiceUpdate(gInstallDirPath);
- }
- }
- EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
-#elif defined(MACOSX)
- if (!isElevated)
- {
- if (gSucceeded)
- {
- LaunchMacPostProcess(gInstallDirPath);
- }
-#endif
-
- LaunchCallbackApp(argv[5],
- argc - callbackIndex,
- argv + callbackIndex,
- sUsingService);
-#ifdef XP_MACOSX
- } // if (!isElevated)
-#endif /* XP_MACOSX */
-}
-return 0;
-}
-
-int NS_main(int argc, NS_tchar **argv)
-{
- // The callback is the remaining arguments starting at callbackIndex.
- // The argument specified by callbackIndex is the callback executable and the
- // argument prior to callbackIndex is the working directory.
- const int callbackIndex = 6;
-
-#ifdef MACOSX
- // TODO: moggi: needs adaptation for LibreOffice
- bool isElevated =
- strstr(argv[0], "/Library/PrivilegedHelperTools/org.mozilla.updater") != 0;
- if (isElevated)
- {
- if (!ObtainUpdaterArguments(&argc, &argv))
- {
- // Won't actually get here because ObtainUpdaterArguments will terminate
- // the current process on failure.
- return 1;
- }
- }
-#endif
-
-#if defined(VERIFY_MAR_SIGNATURE) && !defined(_WIN32) && !defined(MACOSX)
- // On Windows and Mac we rely on native APIs to do verifications so we don't
- // need to initialize NSS at all there.
- // Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS
- // databases.
- if (!NSS_IsInitialized())
- {
- if (NSS_NoDB_Init(NULL) != SECSuccess)
- {
- PRErrorCode error = PR_GetError();
- fprintf(stderr, "Could not initialize NSS: %s (%d)",
- PR_ErrorToName(error), (int) error);
- _exit(1);
- }
- }
-#endif
-
-#ifdef MACOSX
- if (!isElevated)
- {
-#endif
- InitProgressUI(&argc, &argv);
-#ifdef MACOSX
- }
-#endif
-
- // To process an update the updater command line must at a minimum have the
- // directory path containing the updater.mar file to process as the first
- // argument, the install directory as the second argument, and the directory
- // to apply the update to as the third argument. When the updater is launched
- // by another process the PID of the parent process should be provided in the
- // optional fourth argument and the updater will wait on the parent process to
- // exit if the value is non-zero and the process is present. This is necessary
- // due to not being able to update files that are in use on Windows. The
- // optional fifth argument is the callback's working directory and the
- // optional sixth argument is the callback path. The callback is the
- // application to launch after updating and it will be launched when these
- // arguments are provided whether the update was successful or not. All
- // remaining arguments are optional and are passed to the callback when it is
- // launched.
- if (argc < 4)
- {
- fprintf(stderr, "Usage: updater patch-dir install-dir apply-to-dir [wait-pid [callback-working-dir callback-path args...]]\n");
-#ifdef MACOSX
- if (isElevated)
- {
- freeArguments(argc, argv);
- CleanupElevatedMacUpdate(true);
- }
-#endif
- return 1;
- }
-
- // The directory containing the update information.
- gPatchDirPath = argv[1];
-
- // The directory we're going to update to.
- // We copy this string because we need to remove trailing slashes. The C++
- // standard says that it's always safe to write to strings pointed to by argv
- // elements, but I don't necessarily believe it.
- NS_tstrncpy(gInstallDirPath, argv[2], MAXPATHLEN);
- gInstallDirPath[MAXPATHLEN - 1] = NS_T('\0');
- NS_tchar *slash = NS_tstrrchr(gInstallDirPath, NS_SLASH);
- if (slash && !slash[1])
- {
- *slash = NS_T('\0');
- }
-
-#ifdef _WIN32
- bool useService = false;
- bool testOnlyFallbackKeyExists = false;
- bool noServiceFallback = false;
-
- // We never want the service to be used unless we build with
- // the maintenance service.
-#ifdef MAINTENANCE_SERVICE
- useService = IsUpdateStatusPendingService();
- // Our tests run with a different apply directory for each test.
- // We use this registry key on our test slaves to store the
- // allowed name/issuers.
- testOnlyFallbackKeyExists = DoesFallbackKeyExist();
-#endif
-
- // Remove everything except close window from the context menu
- {
- // TODO: moggi: needs adaptation for LibreOffice
- HKEY hkApp = nullptr;
- RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Classes\\Applications",
- 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, nullptr,
- &hkApp, nullptr);
- RegCloseKey(hkApp);
- if (RegCreateKeyExW(HKEY_CURRENT_USER,
- L"Software\\Classes\\Applications\\updater.exe",
- 0, nullptr, REG_OPTION_VOLATILE, KEY_SET_VALUE, nullptr,
- &hkApp, nullptr) == ERROR_SUCCESS)
- {
- RegSetValueExW(hkApp, L"IsHostApp", 0, REG_NONE, 0, 0);
- RegSetValueExW(hkApp, L"NoOpenWith", 0, REG_NONE, 0, 0);
- RegSetValueExW(hkApp, L"NoStartPage", 0, REG_NONE, 0, 0);
- RegCloseKey(hkApp);
- }
- }
-#endif
-
- // If there is a PID specified and it is not '0' then wait for the process to exit.
-#ifdef _WIN32
- __int64 pid = 0;
-#else
- int pid = 0;
-#endif
- if (argc > 4)
- {
-#ifdef _WIN32
- pid = _wtoi64(argv[4]);
-#else
- pid = atoi(argv[4]);
-#endif
- if (pid == -1)
- {
- // This is a signal from the parent process that the updater should stage
- // the update.
- sStagedUpdate = true;
- }
- else if (NS_tstrstr(argv[4], NS_T("/replace")))
- {
- // We're processing a request to replace the application with a staged
- // update.
- sReplaceRequest = true;
- }
- }
-
- // The directory we're going to update to.
- // We copy this string because we need to remove trailing slashes. The C++
- // standard says that it's always safe to write to strings pointed to by argv
- // elements, but I don't necessarily believe it.
- NS_tstrncpy(gWorkingDirPath, argv[3], MAXPATHLEN);
- gWorkingDirPath[MAXPATHLEN - 1] = NS_T('\0');
- slash = NS_tstrrchr(gWorkingDirPath, NS_SLASH);
- if (slash && !slash[1])
- {
- *slash = NS_T('\0');
- }
-
-#ifdef MACOSX
- if (!isElevated && !IsRecursivelyWritable(argv[2]))
- {
- // If the app directory isn't recursively writeable, an elevated update is
- // required.
- UpdateServerThreadArgs threadArgs;
- threadArgs.argc = argc;
- threadArgs.argv = const_cast<const NS_tchar**>(argv);
-
- Thread t1;
- if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0)
- {
- // Show an indeterminate progress bar while an elevated update is in
- // progress.
- ShowProgressUI(true);
- }
- t1.Join();
-
- LaunchCallbackAndPostProcessApps(argc, argv, callbackIndex, false);
- return gSucceeded ? 0 : 1;
- }
-#endif
-
- LogInit(gPatchDirPath, NS_T("update.log"));
-
- if (!WriteStatusFile("applying"))
- {
- LOG(("failed setting status to 'applying'"));
-#ifdef MACOSX
- if (isElevated)
- {
- freeArguments(argc, argv);
- CleanupElevatedMacUpdate(true);
- }
-#endif
- return 1;
- }
-
- if (sStagedUpdate)
- {
- LOG(("Performing a staged update"));
- }
- else if (sReplaceRequest)
- {
- LOG(("Performing a replace request"));
- }
-
- LOG(("PATCH DIRECTORY " LOG_S, gPatchDirPath));
- LOG(("INSTALLATION DIRECTORY " LOG_S, gInstallDirPath));
- LOG(("WORKING DIRECTORY " LOG_S, gWorkingDirPath));
-
-#ifdef _WIN32
- if (_wcsnicmp(gWorkingDirPath, gInstallDirPath, MAX_PATH) != 0)
- {
- if (!sStagedUpdate && !sReplaceRequest)
- {
- WriteStatusFile(INVALID_APPLYTO_DIR_ERROR);
- LOG(("Installation directory and working directory must be the same "
- "for non-staged updates. Exiting."));
- LogFinish();
- return 1;
- }
-
- NS_tchar workingDirParent[MAX_PATH];
- NS_tsnprintf(workingDirParent,
- sizeof(workingDirParent) / sizeof(workingDirParent[0]),
- NS_T("%s"), gWorkingDirPath);
- if (!PathRemoveFileSpecW(workingDirParent))
- {
- WriteStatusFile(REMOVE_FILE_SPEC_ERROR);
- LOG(("Error calling PathRemoveFileSpecW: %d", GetLastError()));
- LogFinish();
- return 1;
- }
-
- if (_wcsnicmp(workingDirParent, gInstallDirPath, MAX_PATH) != 0)
- {
- WriteStatusFile(INVALID_APPLYTO_DIR_STAGED_ERROR);
- LOG(("The apply-to directory must be the same as or "
- "a child of the installation directory! Exiting."));
- LogFinish();
- return 1;
- }
- }
-#endif
-
-
-#ifdef _WIN32
- if (pid > 0)
- {
- HANDLE parent = OpenProcess(SYNCHRONIZE, false, (DWORD) pid);
- // May return nullptr if the parent process has already gone away.
- // Otherwise, wait for the parent process to exit before starting the
- // update.
- if (parent)
- {
- DWORD waitTime = PARENT_WAIT;
- DWORD result = WaitForSingleObject(parent, waitTime);
- CloseHandle(parent);
- if (result != WAIT_OBJECT_0)
- return 1;
- }
- }
-#else
- if (pid > 0)
- waitpid(pid, nullptr, 0);
-#endif
-
-#if defined(_WIN32)
-#ifdef MAINTENANCE_SERVICE
- sUsingService = EnvHasValue("USING_SERVICE");
- putenv(const_cast<char*>("USING_SERVICE="));
-#endif
- // lastFallbackError keeps track of the last error for the service not being
- // used, in case of an error when fallback is not enabled we write the
- // error to the update.status file.
- // When fallback is disabled (MOZ_NO_SERVICE_FALLBACK does not exist) then
- // we will instead fallback to not using the service and display a UAC prompt.
- int lastFallbackError = FALLBACKKEY_UNKNOWN_ERROR;
-
- // Launch a second instance of the updater with the runas verb on Windows
- // when write access is denied to the installation directory.
- HANDLE updateLockFileHandle = INVALID_HANDLE_VALUE;
- NS_tchar elevatedLockFilePath[MAXPATHLEN] = {NS_T('\0')};
- if (!sUsingService &&
- (argc > callbackIndex || sStagedUpdate || sReplaceRequest))
- {
- NS_tchar updateLockFilePath[MAXPATHLEN];
- if (sStagedUpdate)
- {
- // When staging an update, the lock file is:
- // <install_dir>\updated.update_in_progress.lock
- NS_tsnprintf(updateLockFilePath,
- sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]),
- NS_T("%s/updated.update_in_progress.lock"), gInstallDirPath);
- }
- else if (sReplaceRequest)
- {
- // When processing a replace request, the lock file is:
- // <install_dir>\..\moz_update_in_progress.lock
- NS_tchar installDir[MAXPATHLEN];
- NS_tstrcpy(installDir, gInstallDirPath);
- NS_tchar *slash = (NS_tchar *) NS_tstrrchr(installDir, NS_SLASH);
- *slash = NS_T('\0');
- NS_tsnprintf(updateLockFilePath,
- sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]),
- NS_T("%s\\moz_update_in_progress.lock"), installDir);
- }
- else
- {
- // In the non-staging update case, the lock file is:
- // <install_dir>\<app_name>.exe.update_in_progress.lock
- NS_tsnprintf(updateLockFilePath,
- sizeof(updateLockFilePath)/sizeof(updateLockFilePath[0]),
- NS_T("%s.update_in_progress.lock"), argv[callbackIndex]);
- }
-
- // The update_in_progress.lock file should only exist during an update. In
- // case it exists attempt to remove it and exit if that fails to prevent
- // simultaneous updates occurring.
- if (!_waccess(updateLockFilePath, F_OK) &&
- NS_tremove(updateLockFilePath) != 0)
- {
- // Try to fall back to the old way of doing updates if a staged
- // update fails.
- if (sStagedUpdate || sReplaceRequest)
- {
- // Note that this could fail, but if it does, there isn't too much we
- // can do in order to recover anyways.
- WriteStatusFile("pending");
- }
- LOG(("Update already in progress! Exiting"));
- return 1;
- }
-
- updateLockFileHandle = CreateFileW(updateLockFilePath,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- nullptr,
- OPEN_ALWAYS,
- FILE_FLAG_DELETE_ON_CLOSE,
- nullptr);
-
- NS_tsnprintf(elevatedLockFilePath,
- sizeof(elevatedLockFilePath)/sizeof(elevatedLockFilePath[0]),
- NS_T("%s/update_elevated.lock"), gPatchDirPath);
-
- // Even if a file has no sharing access, you can still get its attributes
- bool startedFromUnelevatedUpdater =
- GetFileAttributesW(elevatedLockFilePath) != INVALID_FILE_ATTRIBUTES;
-
- // If we're running from the service, then we were started with the same
- // token as the service so the permissions are already dropped. If we're
- // running from an elevated updater that was started from an unelevated
- // updater, then we drop the permissions here. We do not drop the
- // permissions on the originally called updater because we use its token
- // to start the callback application.
- if (startedFromUnelevatedUpdater)
- {
- // Disable every privilege we don't need. Processes started using
- // CreateProcess will use the same token as this process.
- UACHelper::DisablePrivileges(nullptr);
- }
-
- if (updateLockFileHandle == INVALID_HANDLE_VALUE ||
- (useService && testOnlyFallbackKeyExists && noServiceFallback))
- {
- if (!_waccess(elevatedLockFilePath, F_OK) &&
- NS_tremove(elevatedLockFilePath) != 0)
- {
- fprintf(stderr, "Unable to create elevated lock file! Exiting\n");
- return 1;
- }
-
- HANDLE elevatedFileHandle;
- elevatedFileHandle = CreateFileW(elevatedLockFilePath,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- nullptr,
- OPEN_ALWAYS,
- FILE_FLAG_DELETE_ON_CLOSE,
- nullptr);
-
- if (elevatedFileHandle == INVALID_HANDLE_VALUE)
- {
- LOG(("Unable to create elevated lock file! Exiting"));
- return 1;
- }
-
- wchar_t *cmdLine = MakeCommandLine(argc - 1, argv + 1);
- if (!cmdLine)
- {
- CloseHandle(elevatedFileHandle);
- return 1;
- }
-
- // Make sure the path to the updater to use for the update is on local.
- // We do this check to make sure that file locking is available for
- // race condition security checks.
- if (useService)
- {
- BOOL isLocal = FALSE;
- useService = IsLocalFile(argv[0], isLocal) && isLocal;
- }
-
- // If we have unprompted elevation we should NOT use the service
- // for the update. Service updates happen with the SYSTEM account
- // which has more privs than we need to update with.
- // Windows 8 provides a user interface so users can configure this
- // behavior and it can be configured in the registry in all Windows
- // versions that support UAC.
- if (useService)
- {
- BOOL unpromptedElevation;
- if (IsUnpromptedElevation(unpromptedElevation))
- {
- useService = !unpromptedElevation;
- }
- }
-
- // Make sure the service registry entries for the installation path
- // are available. If not don't use the service.
- if (useService)
- {
- WCHAR maintenanceServiceKey[MAX_PATH + 1];
- // TODO: moggi: needs adaptation for LibreOffice
- // Most likely the registry part is not correct yet
- if (CalculateRegistryPathFromFilePath(gInstallDirPath,
- maintenanceServiceKey))
- {
- HKEY baseKey = nullptr;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- maintenanceServiceKey, 0,
- KEY_READ | KEY_WOW64_64KEY,
- &baseKey) == ERROR_SUCCESS)
- {
- RegCloseKey(baseKey);
- }
- else
- {
-#ifdef TEST_UPDATER
- useService = testOnlyFallbackKeyExists;
-#endif
- if (!useService)
- {
- lastFallbackError = FALLBACKKEY_NOKEY_ERROR;
- }
- }
- }
- else
- {
- useService = false;
- lastFallbackError = FALLBACKKEY_REGPATH_ERROR;
- }
- }
-
- // Originally we used to write "pending" to update.status before
- // launching the service command. This is no longer needed now
- // since the service command is launched from updater.exe. If anything
- // fails in between, we can fall back to using the normal update process
- // on our own.
-
- // If we still want to use the service try to launch the service
- // command for the update.
- if (useService)
- {
- // If the update couldn't be started, then set useService to false so
- // we do the update the old way.
- DWORD ret = LaunchServiceSoftwareUpdateCommand(argc, (LPCWSTR *)argv);
- useService = (ret == ERROR_SUCCESS);
- // If the command was launched then wait for the service to be done.
- if (useService)
- {
- bool showProgressUI = false;
- // Never show the progress UI when staging updates.
- if (!sStagedUpdate)
- {
- // We need to call this separately instead of allowing ShowProgressUI
- // to initialize the strings because the service will move the
- // ini file out of the way when running updater.
- showProgressUI = !InitProgressUIStrings();
- }
-
- // Wait for the service to stop for 5 seconds. If the service
- // has still not stopped then show an indeterminate progress bar.
- DWORD lastState = WaitForServiceStop(SVC_NAME, 5);
- if (lastState != SERVICE_STOPPED)
- {
- std::thread waitThread(WaitForServiceFinishThread, nullptr);
- if (showProgressUI)
- {
- ShowProgressUI(true, false);
- }
- waitThread.join();
- }
-
- lastState = WaitForServiceStop(SVC_NAME, 1);
- if (lastState != SERVICE_STOPPED)
- {
- // If the service doesn't stop after 10 minutes there is
- // something seriously wrong.
- lastFallbackError = FALLBACKKEY_SERVICE_NO_STOP_ERROR;
- useService = false;
- }
- }
- else
- {
- lastFallbackError = FALLBACKKEY_LAUNCH_ERROR;
- }
- }
-
- // If the service can't be used when staging and update, make sure that
- // the UAC prompt is not shown! In this case, just set the status to
- // pending and the update will be applied during the next startup.
- if (!useService && sStagedUpdate)
- {
- if (updateLockFileHandle != INVALID_HANDLE_VALUE)
- {
- CloseHandle(updateLockFileHandle);
- }
- WriteStatusFile("pending");
- return 0;
- }
-
- // If we started the service command, and it finished, check the
- // update.status file to make sure it succeeded, and if it did
- // we need to manually start the PostUpdate process from the
- // current user's session of this unelevated updater.exe the
- // current process is running as.
- // Note that we don't need to do this if we're just staging the update,
- // as the PostUpdate step runs when performing the replacing in that case.
- if (useService && !sStagedUpdate)
- {
- bool updateStatusSucceeded = false;
- if (IsUpdateStatusSucceeded(updateStatusSucceeded) &&
- updateStatusSucceeded)
- {
- if (!LaunchWinPostProcess(gInstallDirPath, gPatchDirPath))
- {
- fprintf(stderr, "The post update process which runs as the user"
- " for service update could not be launched.");
- }
- }
- }
-
- // If we didn't want to use the service at all, or if an update was
- // already happening, or launching the service command failed, then
- // launch the elevated updater.exe as we do without the service.
- // We don't launch the elevated updater in the case that we did have
- // write access all along because in that case the only reason we're
- // using the service is because we are testing.
- if (!useService && !noServiceFallback &&
- updateLockFileHandle == INVALID_HANDLE_VALUE)
- {
- SHELLEXECUTEINFO sinfo;
- memset(&sinfo, 0, sizeof(SHELLEXECUTEINFO));
- sinfo.cbSize = sizeof(SHELLEXECUTEINFO);
- sinfo.fMask = SEE_MASK_FLAG_NO_UI |
- SEE_MASK_FLAG_DDEWAIT |
- SEE_MASK_NOCLOSEPROCESS;
- sinfo.hwnd = nullptr;
- sinfo.lpFile = argv[0];
- sinfo.lpParameters = cmdLine;
- sinfo.lpVerb = L"runas";
- sinfo.nShow = SW_SHOWNORMAL;
-
- bool result = ShellExecuteEx(&sinfo);
- free(cmdLine);
-
- if (result)
- {
- WaitForSingleObject(sinfo.hProcess, INFINITE);
- CloseHandle(sinfo.hProcess);
- }
- else
- {
- WriteStatusFile(ELEVATION_CANCELED);
- }
- }
-
- if (argc > callbackIndex)
- {
- LaunchCallbackApp(argv[5], argc - callbackIndex,
- argv + callbackIndex, sUsingService);
- }
-
- CloseHandle(elevatedFileHandle);
-
- if (!useService && !noServiceFallback &&
- INVALID_HANDLE_VALUE == updateLockFileHandle)
- {
- // We didn't use the service and we did run the elevated updater.exe.
- // The elevated updater.exe is responsible for writing out the
- // update.status file.
- return 0;
- }
- else if (useService)
- {
- // The service command was launched. The service is responsible for
- // writing out the update.status file.
- if (updateLockFileHandle != INVALID_HANDLE_VALUE)
- {
- CloseHandle(updateLockFileHandle);
- }
- return 0;
- }
- else
- {
- // Otherwise the service command was not launched at all.
- // We are only reaching this code path because we had write access
- // all along to the directory and a fallback key existed, and we
- // have fallback disabled (MOZ_NO_SERVICE_FALLBACK env var exists).
- // We only currently use this env var from XPCShell tests.
- CloseHandle(updateLockFileHandle);
- WriteStatusFile(lastFallbackError);
- return 0;
- }
- }
- }
-#endif
-
- if (sStagedUpdate)
- {
- // When staging updates, blow away the old installation directory and create
- // it from scratch.
- ensure_remove_recursive(gWorkingDirPath);
- }
- if (!sReplaceRequest)
- {
- // Try to create the destination directory if it doesn't exist
- int rv = NS_tmkdir(gWorkingDirPath, 0755);
- if (rv != OK && errno != EEXIST)
- {
-#ifdef MACOSX
- if (isElevated)
- {
- freeArguments(argc, argv);
- CleanupElevatedMacUpdate(true);
- }
-#endif
- return 1;
- }
- }
-
-#ifdef _WIN32
- // For replace requests, we don't need to do any real updates, so this is not
- // necessary.
- if (!sReplaceRequest)
- {
- // Allocate enough space for the length of the path an optional additional
- // trailing slash and null termination.
- NS_tchar *destpath = (NS_tchar *) malloc((NS_tstrlen(gWorkingDirPath) + 2) * sizeof(NS_tchar));
- if (!destpath)
- return 1;
-
- NS_tchar *c = destpath;
- NS_tstrcpy(c, gWorkingDirPath);
- c += NS_tstrlen(gWorkingDirPath);
- if (gWorkingDirPath[NS_tstrlen(gWorkingDirPath) - 1] != NS_T('/') &&
- gWorkingDirPath[NS_tstrlen(gWorkingDirPath) - 1] != NS_T('\\'))
- {
- NS_tstrcat(c, NS_T("/"));
- c += NS_tstrlen(NS_T("/"));
- }
- *c = NS_T('\0');
- c++;
-
- gDestPath = destpath;
- }
-
- NS_tchar applyDirLongPath[MAXPATHLEN];
- if (!GetLongPathNameW(gWorkingDirPath, applyDirLongPath,
- sizeof(applyDirLongPath)/sizeof(applyDirLongPath[0])))
- {
- LOG(("NS_main: unable to find apply to dir: " LOG_S, gWorkingDirPath));
- LogFinish();
- WriteStatusFile(WRITE_ERROR_APPLY_DIR_PATH);
- EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
- if (argc > callbackIndex)
- {
- LaunchCallbackApp(argv[5], argc - callbackIndex,
- argv + callbackIndex, sUsingService);
- }
- return 1;
- }
-
- HANDLE callbackFile = INVALID_HANDLE_VALUE;
- if (argc > callbackIndex)
- {
- // If the callback executable is specified it must exist for a successful
- // update. It is important we null out the whole buffer here because later
- // we make the assumption that the callback application is inside the
- // apply-to dir. If we don't have a fully null'ed out buffer it can lead
- // to stack corruption which causes crashes and other problems.
- NS_tchar callbackLongPath[MAXPATHLEN];
- ZeroMemory(callbackLongPath, sizeof(callbackLongPath));
- NS_tchar *targetPath = argv[callbackIndex];
- NS_tchar buffer[MAXPATHLEN * 2] = { NS_T('\0') };
- size_t bufferLeft = MAXPATHLEN * 2;
- if (sReplaceRequest)
- {
- // In case of replace requests, we should look for the callback file in
- // the destination directory.
- size_t commonPrefixLength = PathCommonPrefixW(argv[callbackIndex],
- gInstallDirPath,
- nullptr);
- NS_tchar *p = buffer;
- NS_tstrncpy(p, argv[callbackIndex], commonPrefixLength);
- p += commonPrefixLength;
- bufferLeft -= commonPrefixLength;
- NS_tstrncpy(p, gInstallDirPath + commonPrefixLength, bufferLeft);
-
- size_t len = NS_tstrlen(gInstallDirPath + commonPrefixLength);
- p += len;
- bufferLeft -= len;
- *p = NS_T('\\');
- ++p;
- bufferLeft--;
- *p = NS_T('\0');
- NS_tchar installDir[MAXPATHLEN];
- NS_tstrcpy(installDir, gInstallDirPath);
- size_t callbackPrefixLength = PathCommonPrefixW(argv[callbackIndex],
- installDir,
- nullptr);
- NS_tstrncpy(p, argv[callbackIndex] + std::max(callbackPrefixLength,
- commonPrefixLength), bufferLeft);
- targetPath = buffer;
- }
- if (!GetLongPathNameW(targetPath, callbackLongPath,
- sizeof(callbackLongPath)/sizeof(callbackLongPath[0])))
- {
- LOG(("NS_main: unable to find callback file: " LOG_S, targetPath));
- LogFinish();
- WriteStatusFile(WRITE_ERROR_CALLBACK_PATH);
- EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
- if (argc > callbackIndex)
- {
- LaunchCallbackApp(argv[5],
- argc - callbackIndex,
- argv + callbackIndex,
- sUsingService);
- }
- return 1;
- }
-
- // Doing this is only necessary when we're actually applying a patch.
- if (!sReplaceRequest)
- {
- int len = NS_tstrlen(applyDirLongPath);
- NS_tchar *s = callbackLongPath;
- NS_tchar *d = gCallbackRelPath;
- // advance to the apply to directory and advance past the trailing backslash
- // if present.
- s += len;
- if (*s == NS_T('\\'))
- ++s;
-
- // Copy the string and replace backslashes with forward slashes along the
- // way.
- do
- {
- if (*s == NS_T('\\'))
- *d = NS_T('/');
- else
- *d = *s;
- ++s;
- ++d;
- }
- while (*s);
- *d = NS_T('\0');
- ++d;
-
- // Make a copy of the callback executable so it can be read when patching.
- NS_tsnprintf(gCallbackBackupPath,
- sizeof(gCallbackBackupPath)/sizeof(gCallbackBackupPath[0]),
- NS_T("%s" CALLBACK_BACKUP_EXT), argv[callbackIndex]);
- NS_tremove(gCallbackBackupPath);
- if (!CopyFileW(argv[callbackIndex], gCallbackBackupPath, true))
- {
- DWORD copyFileError = GetLastError();
- LOG(("NS_main: failed to copy callback file " LOG_S
- " into place at " LOG_S, argv[callbackIndex], gCallbackBackupPath));
- LogFinish();
- if (copyFileError == ERROR_ACCESS_DENIED)
- {
- WriteStatusFile(WRITE_ERROR_ACCESS_DENIED);
- }
- else
- {
- WriteStatusFile(WRITE_ERROR_CALLBACK_APP);
- }
-
- EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
- LaunchCallbackApp(argv[callbackIndex],
- argc - callbackIndex,
- argv + callbackIndex,
- sUsingService);
- return 1;
- }
-
- // Since the process may be signaled as exited by WaitForSingleObject before
- // the release of the executable image try to lock the main executable file
- // multiple times before giving up. If we end up giving up, we won't
- // fail the update.
- const int max_retries = 10;
- int retries = 1;
- DWORD lastWriteError = 0;
- do
- {
- // By opening a file handle without FILE_SHARE_READ to the callback
- // executable, the OS will prevent launching the process while it is
- // being updated.
- callbackFile = CreateFileW(targetPath,
- DELETE | GENERIC_WRITE,
- // allow delete, rename, and write
- FILE_SHARE_DELETE | FILE_SHARE_WRITE,
- nullptr, OPEN_EXISTING, 0, nullptr);
- if (callbackFile != INVALID_HANDLE_VALUE)
- break;
-
- lastWriteError = GetLastError();
- LOG(("NS_main: callback app file open attempt %d failed. " \
- "File: " LOG_S ". Last error: %d", retries,
- targetPath, lastWriteError));
-
- Sleep(100);
- }
- while (++retries <= max_retries);
-
- // CreateFileW will fail if the callback executable is already in use.
- if (callbackFile == INVALID_HANDLE_VALUE)
- {
- // Only fail the update if the last error was not a sharing violation.
- if (lastWriteError != ERROR_SHARING_VIOLATION)
- {
- LOG(("NS_main: callback app file in use, failed to exclusively open " \
- "executable file: " LOG_S, argv[callbackIndex]));
- LogFinish();
- if (lastWriteError == ERROR_ACCESS_DENIED)
- {
- WriteStatusFile(WRITE_ERROR_ACCESS_DENIED);
- }
- else
- {
- WriteStatusFile(WRITE_ERROR_CALLBACK_APP);
- }
-
- NS_tremove(gCallbackBackupPath);
- EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
- LaunchCallbackApp(argv[5],
- argc - callbackIndex,
- argv + callbackIndex,
- sUsingService);
- return 1;
- }
- LOG(("NS_main: callback app file in use, continuing without " \
- "exclusive access for executable file: " LOG_S,
- argv[callbackIndex]));
- }
- }
- }
-
- // DELETE_DIR is not required when performing a staged update or replace
- // request; it can be used during a replace request but then it doesn't
- // use gDeleteDirPath.
- if (!sStagedUpdate && !sReplaceRequest)
- {
- // The directory to move files that are in use to on Windows. This directory
- // will be deleted after the update is finished, on OS reboot using
- // MoveFileEx if it contains files that are in use, or by the post update
- // process after the update finishes. On Windows when performing a normal
- // update (e.g. the update is not a staged update and is not a replace
- // request) gWorkingDirPath is the same as gInstallDirPath and
- // gWorkingDirPath is used because it is the destination directory.
- NS_tsnprintf(gDeleteDirPath,
- sizeof(gDeleteDirPath) / sizeof(gDeleteDirPath[0]),
- NS_T("%s/%s"), gWorkingDirPath, DELETE_DIR);
-
- if (NS_taccess(gDeleteDirPath, F_OK))
- {
- NS_tmkdir(gDeleteDirPath, 0755);
- }
- }
-#endif /* _WIN32 */
-
- // Run update process on a background thread. ShowProgressUI may return
- // before QuitProgressUI has been called, so wait for UpdateThreadFunc to
- // terminate. Avoid showing the progress UI when staging an update, or if this
- // is an elevated process on OSX.
- std::thread t(UpdateThreadFunc, nullptr);
- if (!sStagedUpdate && !sReplaceRequest
-#ifdef XP_MACOSX
- && !isElevated
-#endif
- )
- {
- ShowProgressUI();
- }
- t.join();
-
-#ifdef _WIN32
- if (argc > callbackIndex && !sReplaceRequest)
- {
- if (callbackFile != INVALID_HANDLE_VALUE)
- {
- CloseHandle(callbackFile);
- }
- // Remove the copy of the callback executable.
- NS_tremove(gCallbackBackupPath);
- }
-
- if (!sStagedUpdate && !sReplaceRequest && _wrmdir(gDeleteDirPath))
- {
- LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d",
- DELETE_DIR, errno));
- // The directory probably couldn't be removed due to it containing files
- // that are in use and will be removed on OS reboot. The call to remove the
- // directory on OS reboot is done after the calls to remove the files so the
- // files are removed first on OS reboot since the directory must be empty
- // for the directory removal to be successful. The MoveFileEx call to remove
- // the directory on OS reboot will fail if the process doesn't have write
- // access to the HKEY_LOCAL_MACHINE registry key but this is ok since the
- // installer / uninstaller will delete the directory along with its contents
- // after an update is applied, on reinstall, and on uninstall.
- if (MoveFileEx(gDeleteDirPath, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT))
- {
- LOG(("NS_main: directory will be removed on OS reboot: " LOG_S,
- DELETE_DIR));
- }
- else
- {
- LOG(("NS_main: failed to schedule OS reboot removal of " \
- "directory: " LOG_S, DELETE_DIR));
- }
- }
-#endif /* _WIN32 */
-
-
-#ifdef MACOSX
- // When the update is successful remove the precomplete file in the root of
- // the application bundle and move the distribution directory from
- // Contents/MacOS to Contents/Resources and if both exist delete the
- // directory under Contents/MacOS (see Bug 1068439).
- if (gSucceeded && !sStagedUpdate)
- {
- NS_tchar oldPrecomplete[MAXPATHLEN];
- NS_tsnprintf(oldPrecomplete, sizeof(oldPrecomplete)/sizeof(oldPrecomplete[0]),
- NS_T("%s/precomplete"), gInstallDirPath);
- NS_tremove(oldPrecomplete);
-
- NS_tchar oldDistDir[MAXPATHLEN];
- NS_tsnprintf(oldDistDir, sizeof(oldDistDir)/sizeof(oldDistDir[0]),
- NS_T("%s/Contents/MacOS/distribution"), gInstallDirPath);
- int rv = NS_taccess(oldDistDir, F_OK);
- if (!rv)
- {
- NS_tchar newDistDir[MAXPATHLEN];
- NS_tsnprintf(newDistDir, sizeof(newDistDir)/sizeof(newDistDir[0]),
- NS_T("%s/Contents/Resources/distribution"), gInstallDirPath);
- rv = NS_taccess(newDistDir, F_OK);
- if (!rv)
- {
- LOG(("New distribution directory already exists... removing old " \
- "distribution directory: " LOG_S, oldDistDir));
- rv = ensure_remove_recursive(oldDistDir);
- if (rv)
- {
- LOG(("Removing old distribution directory failed - err: %d", rv));
- }
- }
- else
- {
- LOG(("Moving old distribution directory to new location. src: " LOG_S \
- ", dst:" LOG_S, oldDistDir, newDistDir));
- rv = rename_file(oldDistDir, newDistDir, true);
- if (rv)
- {
- LOG(("Moving old distribution directory to new location failed - " \
- "err: %d", rv));
- }
- }
- }
- }
-
- if (isElevated)
- {
- SetGroupOwnershipAndPermissions(gInstallDirPath);
- freeArguments(argc, argv);
- CleanupElevatedMacUpdate(false);
- }
- else if (IsOwnedByGroupAdmin(gInstallDirPath))
- {
- // If the group ownership of the Firefox .app bundle was set to the "admin"
- // group during a previous elevated update, we need to ensure that all files
- // in the bundle have group ownership of "admin" as well as write permission
- // for the group to not break updates in the future.
- SetGroupOwnershipAndPermissions(gInstallDirPath);
- }
-#endif /* MACOSX */
-
- LogFinish();
-
- int retVal = LaunchCallbackAndPostProcessApps(argc, argv, callbackIndex
-#ifdef _WIN32
- , elevatedLockFilePath
- , updateLockFileHandle
-#elif defined(MACOSX)
- , isElevated
-#endif
- );
-
- return retVal ? retVal : (gSucceeded ? 0 : 1);
-}
-
-class ActionList
-{
-public:
- ActionList() : mFirst(nullptr), mLast(nullptr), mCount(0) { }
- ~ActionList();
-
- void Append(Action* action);
- int Prepare();
- int Execute();
- void Finish(int status);
-
-private:
- Action *mFirst;
- Action *mLast;
- int mCount;
-};
-
-ActionList::~ActionList()
-{
- Action* a = mFirst;
- while (a)
- {
- Action *b = a;
- a = a->mNext;
- delete b;
- }
-}
-
-void
-ActionList::Append(Action *action)
-{
- if (mLast)
- mLast->mNext = action;
- else
- mFirst = action;
-
- mLast = action;
- mCount++;
-}
-
-int
-ActionList::Prepare()
-{
- // If the action list is empty then we should fail in order to signal that
- // something has gone wrong. Otherwise we report success when nothing is
- // actually done. See bug 327140.
- if (mCount == 0)
- {
- LOG(("empty action list"));
- return MAR_ERROR_EMPTY_ACTION_LIST;
- }
-
- Action *a = mFirst;
- int i = 0;
- while (a)
- {
- int rv = a->Prepare();
- if (rv)
- return rv;
-
- float percent = float(++i) / float(mCount);
- UpdateProgressUI(PROGRESS_PREPARE_SIZE * percent);
-
- a = a->mNext;
- }
-
- return OK;
-}
-
-int
-ActionList::Execute()
-{
- int currentProgress = 0, maxProgress = 0;
- Action *a = mFirst;
- while (a)
- {
- maxProgress += a->mProgressCost;
- a = a->mNext;
- }
-
- a = mFirst;
- while (a)
- {
- int rv = a->Execute();
- if (rv)
- {
- LOG(("### execution failed"));
- return rv;
- }
-
- currentProgress += a->mProgressCost;
- float percent = float(currentProgress) / float(maxProgress);
- UpdateProgressUI(PROGRESS_PREPARE_SIZE +
- PROGRESS_EXECUTE_SIZE * percent);
-
- a = a->mNext;
- }
-
- return OK;
-}
-
-void
-ActionList::Finish(int status)
-{
- Action *a = mFirst;
- int i = 0;
- while (a)
- {
- a->Finish(status);
-
- float percent = float(++i) / float(mCount);
- UpdateProgressUI(PROGRESS_PREPARE_SIZE +
- PROGRESS_EXECUTE_SIZE +
- PROGRESS_FINISH_SIZE * percent);
-
- a = a->mNext;
- }
-
- if (status == OK)
- gSucceeded = true;
-}
-
-
-#ifdef _WIN32
-int add_dir_entries(const NS_tchar *dirpath, ActionList *list)
-{
- int rv = OK;
- WIN32_FIND_DATAW finddata;
- HANDLE hFindFile;
- NS_tchar searchspec[MAXPATHLEN];
- NS_tchar foundpath[MAXPATHLEN];
-
- NS_tsnprintf(searchspec, sizeof(searchspec)/sizeof(searchspec[0]),
- NS_T("%s*"), dirpath);
- std::unique_ptr<const NS_tchar[]> pszSpec(new_absolute_path(searchspec));
-
- hFindFile = FindFirstFileW(pszSpec.get(), &finddata);
- if (hFindFile != INVALID_HANDLE_VALUE)
- {
- do
- {
- // Don't process the current or parent directory.
- if (NS_tstrcmp(finddata.cFileName, NS_T(".")) == 0 ||
- NS_tstrcmp(finddata.cFileName, NS_T("..")) == 0)
- continue;
-
- NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]),
- NS_T("%s%s"), dirpath, finddata.cFileName);
- if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]),
- NS_T("%s/"), foundpath);
- // Recurse into the directory.
- rv = add_dir_entries(foundpath, list);
- if (rv)
- {
- LOG(("add_dir_entries error: " LOG_S ", err: %d", foundpath, rv));
- return rv;
- }
- }
- else
- {
- // Add the file to be removed to the ActionList.
- NS_tchar *quotedpath = get_quoted_path(foundpath);
- if (!quotedpath)
- return PARSE_ERROR;
-
- Action *action = new RemoveFile();
- rv = action->Parse(quotedpath);
- if (rv)
- {
- LOG(("add_dir_entries Parse error on recurse: " LOG_S ", err: %d",
- quotedpath, rv));
- return rv;
- }
- free(quotedpath);
-
- list->Append(action);
- }
- }
- while (FindNextFileW(hFindFile, &finddata) != 0);
-
- FindClose(hFindFile);
- {
- // Add the directory to be removed to the ActionList.
- NS_tchar *quotedpath = get_quoted_path(dirpath);
- if (!quotedpath)
- return PARSE_ERROR;
-
- Action *action = new RemoveDir();
- rv = action->Parse(quotedpath);
- if (rv)
- LOG(("add_dir_entries Parse error on close: " LOG_S ", err: %d",
- quotedpath, rv));
- else
- list->Append(action);
- free(quotedpath);
- }
- }
-
- return rv;
-}
-
-#elif defined(__sun)
-int add_dir_entries(const NS_tchar *dirpath, ActionList *list)
-{
- int rv = OK;
- NS_tchar foundpath[MAXPATHLEN];
- struct
- {
- dirent dent_buffer;
- char chars[MAXNAMLEN];
- } ent_buf;
- struct dirent* ent;
- std::unique_ptr<NS_tchar[]> searchpath(new_absolute_path(dirpath));
-
- DIR* dir = opendir(searchpath.get());
- if (!dir)
- {
- LOG(("add_dir_entries error on opendir: " LOG_S ", err: %d", searchpath.get(),
- errno));
- return UNEXPECTED_FILE_OPERATION_ERROR;
- }
-
- while (readdir_r(dir, (dirent *)&ent_buf, &ent) == 0 && ent)
- {
- if ((strcmp(ent->d_name, ".") == 0) ||
- (strcmp(ent->d_name, "..") == 0))
- continue;
-
- NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]),
- NS_T("%s%s"), searchpath.get(), ent->d_name);
- struct stat64 st_buf;
- int test = stat64(foundpath, &st_buf);
- if (test)
- {
- closedir(dir);
- return UNEXPECTED_FILE_OPERATION_ERROR;
- }
- if (S_ISDIR(st_buf.st_mode))
- {
- NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]),
- NS_T("%s/"), foundpath);
- // Recurse into the directory.
- rv = add_dir_entries(foundpath, list);
- if (rv)
- {
- LOG(("add_dir_entries error: " LOG_S ", err: %d", foundpath, rv));
- closedir(dir);
- return rv;
- }
- }
- else
- {
- // Add the file to be removed to the ActionList.
- NS_tchar *quotedpath = get_quoted_path(get_relative_offset(foundpath));
- if (!quotedpath)
- {
- closedir(dir);
- return PARSE_ERROR;
- }
-
- Action *action = new RemoveFile();
- rv = action->Parse(quotedpath);
- if (rv)
- {
- LOG(("add_dir_entries Parse error on recurse: " LOG_S ", err: %d",
- quotedpath, rv));
- closedir(dir);
- return rv;
- }
-
- list->Append(action);
- }
- }
- closedir(dir);
-
- // Add the directory to be removed to the ActionList.
- NS_tchar *quotedpath = get_quoted_path(get_relative_offset(dirpath));
- if (!quotedpath)
- return PARSE_ERROR;
-
- Action *action = new RemoveDir();
- rv = action->Parse(quotedpath);
- if (rv)
- {
- LOG(("add_dir_entries Parse error on close: " LOG_S ", err: %d",
- quotedpath, rv));
- }
- else
- {
- list->Append(action);
- }
-
- return rv;
-}
-
-#else
-
-int add_dir_entries(const NS_tchar *dirpath, ActionList *list)
-{
- int rv = OK;
- FTS *ftsdir;
- FTSENT *ftsdirEntry;
- std::unique_ptr<NS_tchar[]> searchpath(new_absolute_path(dirpath));
-
- // Remove the trailing slash so the paths don't contain double slashes. The
- // existence of the slash has already been checked in DoUpdate.
- searchpath.get()[NS_tstrlen(searchpath.get()) - 1] = NS_T('\0');
- char* const pathargv[] = {searchpath.get(), nullptr};
-
- // FTS_NOCHDIR is used so relative paths from the destination directory are
- // returned.
- if (!(ftsdir = fts_open(pathargv,
- FTS_PHYSICAL | FTS_NOSTAT | FTS_XDEV | FTS_NOCHDIR,
- nullptr)))
- return UNEXPECTED_FILE_OPERATION_ERROR;
-
- while ((ftsdirEntry = fts_read(ftsdir)) != nullptr)
- {
- NS_tchar foundpath[MAXPATHLEN];
- NS_tchar *quotedpath = nullptr;
- Action *action = nullptr;
-
- switch (ftsdirEntry->fts_info)
- {
- // Filesystem objects that shouldn't be in the application's directories
- case FTS_SL:
- case FTS_SLNONE:
- case FTS_DEFAULT:
- LOG(("add_dir_entries: found a non-standard file: " LOG_S,
- ftsdirEntry->fts_path));
- /* Fall through */ // and try to remove as a file
-
- // Files
- case FTS_F:
- case FTS_NSOK:
- // Add the file to be removed to the ActionList.
- NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]),
- NS_T("%s"), ftsdirEntry->fts_accpath);
- quotedpath = get_quoted_path(get_relative_offset(foundpath));
- if (!quotedpath)
- {
- rv = UPDATER_QUOTED_PATH_MEM_ERROR;
- break;
- }
- action = new RemoveFile();
- rv = action->Parse(quotedpath);
- free(quotedpath);
- if (!rv)
- list->Append(action);
- break;
-
- // Directories
- case FTS_DP:
- rv = OK;
- // Add the directory to be removed to the ActionList.
- NS_tsnprintf(foundpath, sizeof(foundpath)/sizeof(foundpath[0]),
- NS_T("%s/"), ftsdirEntry->fts_accpath);
- quotedpath = get_quoted_path(get_relative_offset(foundpath));
- if (!quotedpath)
- {
- rv = UPDATER_QUOTED_PATH_MEM_ERROR;
- break;
- }
-
- action = new RemoveDir();
- rv = action->Parse(quotedpath);
- free(quotedpath);
- if (!rv)
- list->Append(action);
- break;
-
- // Errors
- case FTS_DNR:
- case FTS_NS:
- // ENOENT is an acceptable error for FTS_DNR and FTS_NS and means that
- // we're racing with ourselves. Though strange, the entry will be
- // removed anyway.
- if (ENOENT == ftsdirEntry->fts_errno)
- {
- rv = OK;
- break;
- }
- // Fall through
-
- case FTS_ERR:
- rv = UNEXPECTED_FILE_OPERATION_ERROR;
- LOG(("add_dir_entries: fts_read() error: " LOG_S ", err: %d",
- ftsdirEntry->fts_path, ftsdirEntry->fts_errno));
- break;
-
- case FTS_DC:
- rv = UNEXPECTED_FILE_OPERATION_ERROR;
- LOG(("add_dir_entries: fts_read() returned FT_DC: " LOG_S,
- ftsdirEntry->fts_path));
- break;
-
- default:
- // FTS_D is ignored and FTS_DP is used instead (post-order).
- rv = OK;
- break;
- }
-
- if (rv != OK)
- break;
- }
-
- fts_close(ftsdir);
-
- return rv;
-}
-#endif
-
-static NS_tchar*
-GetManifestContents(const NS_tchar *manifest)
-{
- AutoFile mfile(NS_tfopen(manifest, NS_T("rb")));
- if (mfile == nullptr)
- {
- LOG(("GetManifestContents: error opening manifest file: " LOG_S, manifest));
- return nullptr;
- }
-
- struct stat ms;
- int rv = fstat(fileno((FILE *)mfile), &ms);
- if (rv)
- {
- LOG(("GetManifestContents: error stating manifest file: " LOG_S, manifest));
- return nullptr;
- }
-
- char *mbuf = (char *) malloc(ms.st_size + 1);
- if (!mbuf)
- return nullptr;
-
- size_t r = ms.st_size;
- char *rb = mbuf;
- while (r)
- {
- const size_t count = std::min<size_t>(SSIZE_MAX, r);
- size_t c = fread(rb, 1, count, mfile);
- if (c != count)
- {
- LOG(("GetManifestContents: error reading manifest file: " LOG_S, manifest));
- free(mbuf);
- return nullptr;
- }
-
- r -= c;
- rb += c;
- }
- mbuf[ms.st_size] = '\0';
- rb = mbuf;
-
-#ifndef _WIN32
- return rb;
-#else
- NS_tchar *wrb = (NS_tchar *) malloc((ms.st_size + 1) * sizeof(NS_tchar));
- if (!wrb)
- {
- free(mbuf);
- return nullptr;
- }
-
- if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, rb, -1, wrb,
- ms.st_size + 1))
- {
- LOG(("GetManifestContents: error converting utf8 to utf16le: %d", GetLastError()));
- free(mbuf);
- free(wrb);
- return nullptr;
- }
- free(mbuf);
-
- return wrb;
-#endif
-}
-
-int AddPreCompleteActions(ActionList *list)
-{
-#ifdef MACOSX
- std::unique_ptr<NS_tchar[]> manifestPath(new_absolute_path(
- NS_T("Contents/Resources/precomplete")));
-#else
- std::unique_ptr<NS_tchar[]> manifestPath(new_absolute_path(
- NS_T("precomplete")));
-#endif
-
- NS_tchar *rb = GetManifestContents(manifestPath.get());
- if (rb == nullptr)
- {
- LOG(("AddPreCompleteActions: error getting contents of precomplete " \
- "manifest"));
- // Applications aren't required to have a precomplete manifest. The mar
- // generation scripts enforce the presence of a precomplete manifest.
- return OK;
- }
-
- int rv;
- NS_tchar *line;
- while ((line = mstrtok(kNL, &rb)) != 0)
- {
- // skip comments
- if (*line == NS_T('#'))
- continue;
-
- NS_tchar *token = mstrtok(kWhitespace, &line);
- if (!token)
- {
- LOG(("AddPreCompleteActions: token not found in manifest"));
- return PARSE_ERROR;
- }
-
- Action *action = nullptr;
- if (NS_tstrcmp(token, NS_T("remove")) == 0) // rm file
- {
- action = new RemoveFile();
- }
- else if (NS_tstrcmp(token, NS_T("remove-cc")) == 0) // no longer supported
- {
- continue;
- }
- else if (NS_tstrcmp(token, NS_T("rmdir")) == 0) // rmdir if empty
- {
- action = new RemoveDir();
- }
- else
- {
- LOG(("AddPreCompleteActions: unknown token: " LOG_S, token));
- return PARSE_ERROR;
- }
-
- if (!action)
- return BAD_ACTION_ERROR;
-
- rv = action->Parse(line);
- if (rv)
- return rv;
-
- list->Append(action);
- }
-
- return OK;
-}
-
-int DoUpdate(ArchiveReader& archiveReader)
-{
- NS_tchar manifest[MAXPATHLEN];
- int nWrittenBytes = NS_tsnprintf(manifest, sizeof(manifest)/sizeof(manifest[0]),
- NS_T("%s/updating/update.manifest"), gWorkingDirPath);
- (void) nWrittenBytes;
- ensure_parent_dir(manifest);
-
- // extract the manifest
- // TODO: moggi: needs adaptation for LibreOffice
- // Why would we need the manifest? Even if we need it why would we need 2?
- int rv = archiveReader.ExtractFile("updatev3.manifest", manifest);
- if (rv)
- {
- rv = archiveReader.ExtractFile("updatev2.manifest", manifest);
- if (rv)
- {
- LOG(("DoUpdate: error extracting manifest file"));
- return rv;
- }
- }
-
- NS_tchar *rb = GetManifestContents(manifest);
- NS_tremove(manifest);
- if (rb == nullptr)
- {
- LOG(("DoUpdate: error opening manifest file: " LOG_S, manifest));
- return READ_ERROR;
- }
-
- ActionList list;
- NS_tchar *line;
- bool isFirstAction = true;
-
- while ((line = mstrtok(kNL, &rb)) != 0)
- {
- // skip comments
- if (*line == NS_T('#'))
- continue;
-
- NS_tchar *token = mstrtok(kWhitespace, &line);
- if (!token)
- {
- LOG(("DoUpdate: token not found in manifest"));
- return PARSE_ERROR;
- }
-
- if (isFirstAction)
- {
- isFirstAction = false;
- // The update manifest isn't required to have a type declaration. The mar
- // generation scripts enforce the presence of the type declaration.
- if (NS_tstrcmp(token, NS_T("type")) == 0)
- {
- const NS_tchar *type = mstrtok(kQuote, &line);
- LOG(("UPDATE TYPE " LOG_S, type));
- if (NS_tstrcmp(type, NS_T("complete")) == 0)
- {
- rv = AddPreCompleteActions(&list);
- if (rv)
- return rv;
- }
- continue;
- }
- }
-
- Action *action = nullptr;
- if (NS_tstrcmp(token, NS_T("remove")) == 0) // rm file
- {
- action = new RemoveFile();
- }
- else if (NS_tstrcmp(token, NS_T("rmdir")) == 0) // rmdir if empty
- {
- action = new RemoveDir();
- }
- else if (NS_tstrcmp(token, NS_T("rmrfdir")) == 0) // rmdir recursive
- {
- const NS_tchar *reldirpath = mstrtok(kQuote, &line);
- if (!reldirpath)
- return PARSE_ERROR;
-
- if (reldirpath[NS_tstrlen(reldirpath) - 1] != NS_T('/'))
- return PARSE_ERROR;
-
- rv = add_dir_entries(reldirpath, &list);
- if (rv)
- return rv;
-
- continue;
- }
- else if (NS_tstrcmp(token, NS_T("add")) == 0)
- {
- action = new AddFile(archiveReader);
- }
- else if (NS_tstrcmp(token, NS_T("patch")) == 0)
- {
- action = new PatchFile(archiveReader);
- }
- else if (NS_tstrcmp(token, NS_T("add-if")) == 0) // Add if exists
- {
- action = new AddIfFile(archiveReader);
- }
- else if (NS_tstrcmp(token, NS_T("add-if-not")) == 0) // Add if not exists
- {
- action = new AddIfNotFile(archiveReader);
- }
- else if (NS_tstrcmp(token, NS_T("patch-if")) == 0) // Patch if exists
- {
- action = new PatchIfFile(archiveReader);
- }
- else
- {
- LOG(("DoUpdate: unknown token: " LOG_S, token));
- return PARSE_ERROR;
- }
-
- if (!action)
- return BAD_ACTION_ERROR;
-
- rv = action->Parse(line);
- if (rv)
- return rv;
-
- list.Append(action);
- }
-
- rv = list.Prepare();
- if (rv)
- return rv;
-
- rv = list.Execute();
-
- list.Finish(rv);
- return rv;
-}
diff --git a/onlineupdate/source/update/updater/updater.exe.comctl32.manifest b/onlineupdate/source/update/updater/updater.exe.comctl32.manifest
deleted file mode 100644
index 9a6cdb565fe1..000000000000
--- a/onlineupdate/source/update/updater/updater.exe.comctl32.manifest
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
-<assemblyIdentity
- version="1.0.0.0"
- processorArchitecture="*"
- name="Updater"
- type="win32"
-/>
-<description>Updater</description>
-<dependency>
- <dependentAssembly>
- <assemblyIdentity
- type="win32"
- name="Microsoft.Windows.Common-Controls"
- version="6.0.0.0"
- processorArchitecture="*"
- publicKeyToken="6595b64144ccf1df"
- language="*"
- />
- </dependentAssembly>
-</dependency>
-<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
- <ms_asmv3:security>
- <ms_asmv3:requestedPrivileges>
- <ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" />
- </ms_asmv3:requestedPrivileges>
- </ms_asmv3:security>
-</ms_asmv3:trustInfo>
- <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
- <application>
- <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
- <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
- <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
- <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
- <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
- </application>
- </compatibility>
-</assembly>
diff --git a/onlineupdate/source/update/updater/updater.exe.manifest b/onlineupdate/source/update/updater/updater.exe.manifest
deleted file mode 100644
index cd229c954109..000000000000
--- a/onlineupdate/source/update/updater/updater.exe.manifest
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
-<assemblyIdentity
- version="1.0.0.0"
- processorArchitecture="*"
- name="Updater"
- type="win32"
-/>
-<description>Updater</description>
-<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
- <ms_asmv3:security>
- <ms_asmv3:requestedPrivileges>
- <ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" />
- </ms_asmv3:requestedPrivileges>
- </ms_asmv3:security>
-</ms_asmv3:trustInfo>
- <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
- <application>
- <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
- <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
- <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
- <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
- <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
- </application>
- </compatibility>
-</assembly>
diff --git a/onlineupdate/source/update/updater/updater.ico b/onlineupdate/source/update/updater/updater.ico
deleted file mode 100644
index 7b20ba3ec3ce..000000000000
--- a/onlineupdate/source/update/updater/updater.ico
+++ /dev/null
Binary files differ
diff --git a/onlineupdate/source/update/updater/updater.png b/onlineupdate/source/update/updater/updater.png
deleted file mode 100644
index 9d8c6df7789a..000000000000
--- a/onlineupdate/source/update/updater/updater.png
+++ /dev/null
Binary files differ
diff --git a/onlineupdate/source/update/updater/updater.rc b/onlineupdate/source/update/updater/updater.rc
deleted file mode 100644
index d77cea2fee90..000000000000
--- a/onlineupdate/source/update/updater/updater.rc
+++ /dev/null
@@ -1,137 +0,0 @@
-/* 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/. */
-
-// Microsoft Visual C++ generated resource script.
-//
-#ifdef TEST_UPDATER
-#include "../resource.h"
-#define MANIFEST_PATH "../updater.exe.manifest"
-#define COMCTL32_MANIFEST_PATH "../updater.exe.comctl32.manifest"
-#define ICON_PATH "../updater.ico"
-#else
-#include "resource.h"
-#define MANIFEST_PATH "updater.exe.manifest"
-#define COMCTL32_MANIFEST_PATH "updater.exe.comctl32.manifest"
-#define ICON_PATH "updater.ico"
-#endif
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "winresrc.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// RT_MANIFEST
-//
-
-1 RT_MANIFEST MANIFEST_PATH
-IDR_COMCTL32_MANIFEST RT_MANIFEST COMCTL32_MANIFEST_PATH
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-IDI_DIALOG ICON ICON_PATH
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Embedded an identifier to uniquely identify this as a Mozilla updater.
-//
-
-STRINGTABLE
-{
- IDS_UPDATER_IDENTITY, "libreoffice-updater.exe-7bab28a0-0599-4f37-9efe-f7f8b71f05e3"
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Dialog
-//
-
-IDD_DIALOG DIALOGEX 0, 0, 253, 41
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,24,239,10
- LTEXT "",IDC_INFO,7,8,239,13,SS_NOPREFIX
-END
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// DESIGNINFO
-//
-
-#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO
-BEGIN
- IDD_DIALOG, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 246
- TOPMARGIN, 7
- BOTTOMMARGIN, 39
- END
-END
-#endif // APSTUDIO_INVOKED
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""winresrc.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/onlineupdate/source/update/updater/updater.svg b/onlineupdate/source/update/updater/updater.svg
deleted file mode 100644
index 6a3e88563283..000000000000
--- a/onlineupdate/source/update/updater/updater.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="32" viewBox="0 0 32 32.000001" width="32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="5" cy="13.375" gradientTransform="matrix(2.6502653 .00000002 0 1.1249099 -5.937606 7.116442)" gradientUnits="userSpaceOnUse" r="5" xlink:href="#b"/><linearGradient id="b"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity=".487603"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="312.625" x2="312.0625" xlink:href="#d" y1="196.541335" y2="191.797335"/><linearGradient id="d"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><filter id="e" color-interpolation-filters="sRGB" height="1.588154" width="1.259382" x="-.129691" y="-.294077"><feGaussianBlur stdDeviation=".86460582"/></filter><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="17.92817" x2="17.92817" y1="8.43984" y2="5.29526"><stop offset="0" stop-color="#e9b96e"/><stop offset="1" stop-color="#eeeeec"/></linearGradient><linearGradient id="g" gradientTransform="matrix(.06998908 0 0 .06896555 12.18409 2.80365)" gradientUnits="userSpaceOnUse" x1="174.01562" x2="30" y1="236" y2="64"><stop offset="0" stop-color="#c17d11"/><stop offset="1" stop-color="#e9b96e"/></linearGradient><radialGradient id="h" cx="321.86331" cy="70.499977" gradientTransform="matrix(.6227245 0 0 .09677408 -177.2342 3.75694)" gradientUnits="userSpaceOnUse" r="15.500023"><stop offset="0" stop-color="#faefde"/><stop offset=".68321055" stop-color="#e9b96e"/><stop offset="1" stop-color="#e9b96e" stop-opacity="0"/></radialGradient><radialGradient id="i" cx="321.7785" cy="91.857727" gradientTransform="matrix(2.0837843 0 0 .3006166 -644.48535 -10.03444)" gradientUnits="userSpaceOnUse" r="15.5"><stop offset="0" stop-color="#e9b96e"/><stop offset="1" stop-color="#e9b96e" stop-opacity="0"/></radialGradient><radialGradient id="j" cx="323.89844" cy="70.5" gradientTransform="matrix(.3715153 0 0 .3516126 -97.26516 -14.20919)" gradientUnits="userSpaceOnUse" r="15.5" xlink:href="#b"/><linearGradient id="k" gradientTransform="matrix(.3791614 0 0 .6106884 -99.96394 -32.72591)" gradientUnits="userSpaceOnUse" x1="316.90683" x2="322.41666" xlink:href="#d" y1="69.553268" y2="69.553268"/><linearGradient id="l" gradientTransform="matrix(.970062 -.2428574 0 1 -362.71624 -176.92048)" gradientUnits="userSpaceOnUse" x1="394.59244" x2="389.02057" y1="277.23956" y2="280.54391"><stop offset="0" stop-color="#eeeeec"/><stop offset="1" stop-color="#e9b96e"/></linearGradient><linearGradient id="m" gradientTransform="matrix(.3925197 0 0 .6106884 -104.79786 -32.72591)" gradientUnits="userSpaceOnUse" x1="333.88629" x2="326.32867" xlink:href="#d" y1="69.490768" y2="69.490768"/><linearGradient id="n" gradientTransform="matrix(1.0000001 1.0190348 0 1.0165713 -342.71627 -558.00916)" gradientUnits="userSpaceOnUse" x1="373.8385" x2="375.07596" y1="187.7484" y2="181.79832"><stop offset="0" stop-color="#e9b96e"/><stop offset="1" stop-color="#c17d11"/></linearGradient><linearGradient id="o" gradientUnits="userSpaceOnUse" x1="19.53376" x2="22.28376" xlink:href="#b" y1="14.70452" y2="5.98577"/><linearGradient id="p" gradientUnits="userSpaceOnUse" x1="24.81501" x2="27.63508" xlink:href="#b" y1="5.51702" y2="7.37133"/><linearGradient id="q" gradientTransform="matrix(.970062 -.2428574 0 1 -362.71624 -176.92048)" gradientUnits="userSpaceOnUse" x1="391.0188" x2="389.73026" xlink:href="#b" y1="277.72043" y2="279.4614"/><filter id="r" color-interpolation-filters="sRGB" height="1.86087" width="1.2475" x="-.12375" y="-.430435"><feGaussianBlur stdDeviation=".515625"/></filter><radialGradient id="s" cx="5" cy="13.375" gradientTransform="matrix(2.6502653 .00000002 0 1.1249099 1.062394 13.293218)" gradientUnits="userSpaceOnUse" r="5" xlink:href="#b"/><linearGradient id="t" gradientTransform="matrix(1.2807984 0 0 1.2807976 -376.53809 -266.21095)" gradientUnits="userSpaceOnUse" x1="305.62964" x2="299.38138" y1="222.08656" y2="217.11935"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#babdb6"/></linearGradient><rect fill="url(#c)" filter="url(#e)" height="7.056155" opacity=".753425" rx="1.3125" transform="matrix(1.0441942 0 0 1 -306.59321 -176.92048)" width="16" x="306" y="190.17233"/><rect filter="url(#r)" height="2.875" opacity=".579208" rx="1.25" ry="1.4375" transform="matrix(1.15 0 0 1 -591.83312 5.636224)" width="10" x="515.875" y="16.625"/><rect fill="#d9a452" fill-rule="evenodd" height="8.000001" rx=".09427" ry=".094274" stroke="#8f5902" width="9.015612" x="2.798108" y="16.474611"/><rect fill="#e8c48d" fill-rule="evenodd" height="4.1875" rx=".09427" ry=".094274" transform="scale(-1 1)" width="8.125" x="-11.37622" y="16.912111"/><path d="m3.75122 17.412112v6.125h7.125v-6.125z" fill="none" opacity=".439759" stroke="url(#a)"/><path d="m4.2582637 17.108049 7.3125003-.151651-.170181.91895-6.9783737.173896-.1639456 2.064009 7.0710683-.08839.08839 1.149048-8.1317282-.08839-.088388-4.154253z" fill="#f5efe4" fill-rule="evenodd"/><rect filter="url(#r)" height="2.875" opacity=".579208" rx="1.25" ry="1.4375" transform="matrix(1.15 0 0 1 -584.83312 11.636224)" width="10" x="515.875" y="16.625"/><rect fill="#d9a452" fill-rule="evenodd" height="8.000001" rx=".09427" ry=".094274" stroke="#8f5902" width="9.015612" x="9.798108" y="22.651388"/><rect fill="#e8c48d" fill-rule="evenodd" height="4.1875" rx=".09427" ry=".094274" transform="scale(-1 1)" width="8.125" x="-18.376221" y="23.088888"/><path d="m10.75122 23.588888v6.125h7.125v-6.125z" fill="none" opacity=".439759" stroke="url(#s)"/><path d="m11.258264 23.284825 7.3125-.151651-7.18713.986747-.12537 2.170108 7.071068-.08839.08839 1.149048-8.131727-.08839-.08839-4.154253 1.060661.176777z" fill="#f5efe4" fill-rule="evenodd"/><rect fill="url(#f)" height="14.999985" rx="1.016466" stroke="#8f5902" stroke-dashoffset=".5" stroke-linecap="round" stroke-linejoin="round" width="15" x="13.78376" y="4.579536"/><path d="m18.28175 8.07952h7.90593v1.00676h-7.90593z" fill="#fff" opacity=".2"/><path d="m14.7037 10.07952c-.23265 0-.41994.18455-.41994.41378v7.89657.27586c0 .22924.18729.41379.41994.41379h13.16012c.23265 0 .41994-.18455.41994-.41379v-8.17243c0-.22923-.18729-.41378-.41994-.41378z" fill="url(#g)" fill-rule="evenodd"/><path d="m14.78376 5.57952h13v13.00002h-13z" style="opacity:.342342;fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:.5;stroke:url(#o)"/><path d="m14.34513 9.07952-.0562 2.96875 13.98983.0312-.0562-3h-13.87753z" fill="url(#h)" fill-rule="evenodd" opacity=".5"/><path d="m14.7037 10.07952c-.23265 0-.41994.18454-.41994.41379v7.89655.27587c0 .22925.18729.41379.41994.41379h13.16012c.23265 0 .41994-.18455.41994-.41379v-8.17242c0-.22925-.18729-.41379-.41994-.41379z" fill="url(#i)" fill-rule="evenodd" opacity=".815315"/><path d="m14.28376 10.07952h14v1h-14z" fill="url(#j)" opacity=".747748"/><path d="m18.28175 7.07952h6.18718v1.00676h-6.18718z" fill="#c17d11" opacity=".40991"/><path d="m16.3849 5.07952c-.0485 0-.0757.0294-.11659.11449-.0409.0851-.0772.2227-.10363.3626l-.88092 4.52291h7v-5z" fill="url(#k)" fill-rule="evenodd" opacity=".468468"/><path d="m13.783748 9.4403349v-3.97196c0-.56176.453339-1.1275045 1.01646-1.2684833l4.955804-1.2406977c.563131-.1409811 1.01647.1977743 1.01647.7595343v3.97196c0 .56176-.453339 1.1275046-1.01647 1.2684857l-4.03474.6503971" fill="url(#l)" stroke="#8f5902" stroke-dashoffset=".5" stroke-linecap="round" stroke-linejoin="round"/><path d="m22.28376 5.07952v5h5l-.99706-4.59925c-.0288-.13456-.0614-.26033-.10264-.32442-.04126-.06408-.0783-.07633-.14664-.07633z" fill="url(#m)" fill-rule="evenodd" opacity=".468468"/><path d="m28.78376 10.14202v-4.03125c0-.57245-.46814-1.48866-1.03125-2.0625l-2.9375-3.03125s-.48496-.76809-1.71875-.4375c-.18373-.00045-.3125.15128-.3125.4375v4.03125c0 .57245.46812 1.48866 1.03125 2.0625l3.00562 2.51312" fill="url(#n)" stroke="#8f5902" stroke-dashoffset=".5" stroke-linecap="round" stroke-linejoin="round"/><path d="m13.271484 6.2226562c-5.2651384 1.0467841-9.271484 5.7180798-9.271484 11.2773438 0 6.321666 5.1783326 11.5 11.5 11.5 6.321667 0 11.5-5.178334 11.5-11.5 0-4.428937-2.546314-8.2880167-6.242188-10.2070312v6.3710932c.779838 1.072341 1.242188 2.393081 1.242188 3.835938 0 3.619464-2.880531 6.5-6.5 6.5s-6.5-2.880536-6.5-6.5c0-2.833183 1.768714-5.206891 4.271484-6.107422z" fill="#888a85"/><g fill="none"><g stroke-linecap="round"><path d="m23.75251 1.52093v3.52734c0 .0439.36048.96696.74609 1.37109l2.77344 2.31055.54297.14649v-2.76563c0-.0443-.36385-.98728-.75391-1.38477a.96884687.96884687 0 0 1 -.004-.004l-2.9375-3.03125a.96884687.96884687 0 0 1 -.12305-.15625s.0335.0321-.043-.01c-.0253-.0139-.15681.009-.20117-.004z" opacity=".572072" stroke="url(#p)" stroke-dashoffset=".5" stroke-linejoin="round"/><path d="m23.69001 1.32952c.14068 1.70518-.31678 3.76924.5625 5.03125" opacity=".414414" stroke="#fff"/><path d="m14.819765 5.2499556v3.16797l1.115949.097569 3.794989-.6258648v-3.86914z" opacity=".716216" stroke="url(#q)" stroke-dashoffset=".5"/></g><path d="m24.78174 9.58626h-5v5" stroke="#888a85" stroke-linecap="square" stroke-width="5"/></g><path d="m13.322266 7.2519531c-4.740376 1.0081786-8.322266 5.2153889-8.322266 10.2480469 0 5.781225 4.7187725 10.5 10.5 10.5 5.781228 0 10.5-4.718775 10.5-10.5 0-4.918766-3.420176-9.0588504-8-10.1875v3.119141c2.91831 1.024849 5 3.787879 5 7.068359 0 4.159904-3.340092 7.499999-7.5 7.5-4.159908 0-7.5-3.340096-7.5-7.5 0-3.399893 2.235404-6.239226 5.322266-7.166016z" fill="url(#t)"/><path d="m24.78174 9.58626h-5v5" fill="none" stroke="#fff" stroke-linecap="square" stroke-width="3"/><path d="m17.281748 7.0863v1 6h1v-6h7v-1h-7z" fill="#888a85"/></svg> \ No newline at end of file
diff --git a/onlineupdate/source/update/updater/win_dirent.cxx b/onlineupdate/source/update/updater/win_dirent.cxx
deleted file mode 100644
index 2368613ee42b..000000000000
--- a/onlineupdate/source/update/updater/win_dirent.cxx
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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/. */
-
-#ifdef _WIN32
-#include "win_dirent.h"
-#include <errno.h>
-#include <string.h>
-
-// This file implements the minimum set of dirent APIs used by updater.cpp on
-// Windows. If updater.cpp is modified to use more of this API, we need to
-// implement those parts here too.
-
-static dirent gDirEnt;
-
-DIR::DIR(const WCHAR* path)
- : findHandle(INVALID_HANDLE_VALUE)
-{
- memset(name, 0, sizeof(name));
- wcsncpy(name, path, sizeof(name)/sizeof(name[0]));
- wcsncat(name, L"\\*", sizeof(name)/sizeof(name[0]) - wcslen(name) - 1);
-}
-
-DIR::~DIR()
-{
- if (findHandle != INVALID_HANDLE_VALUE)
- {
- FindClose(findHandle);
- }
-}
-
-dirent::dirent()
-{
- d_name[0] = L'\0';
-}
-
-DIR*
-opendir(const WCHAR* path)
-{
- return new DIR(path);
-}
-
-int
-closedir(DIR* dir)
-{
- delete dir;
- return 0;
-}
-
-dirent* readdir(DIR* dir)
-{
- WIN32_FIND_DATAW data;
- if (dir->findHandle != INVALID_HANDLE_VALUE)
- {
- BOOL result = FindNextFileW(dir->findHandle, &data);
- if (!result)
- {
- if (GetLastError() != ERROR_FILE_NOT_FOUND)
- {
- errno = ENOENT;
- }
- return 0;
- }
- }
- else
- {
- // Reading the first directory entry
- dir->findHandle = FindFirstFileW(dir->name, &data);
- if (dir->findHandle == INVALID_HANDLE_VALUE)
- {
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
- {
- errno = ENOENT;
- }
- else
- {
- errno = EBADF;
- }
- return 0;
- }
- }
- memset(gDirEnt.d_name, 0, sizeof(gDirEnt.d_name));
- wcsncpy(gDirEnt.d_name, data.cFileName,
- sizeof(gDirEnt.d_name)/sizeof(gDirEnt.d_name[0]));
- return &gDirEnt;
-}
-#endif
diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx
deleted file mode 100644
index 17ee57ec400f..000000000000
--- a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx
+++ /dev/null
@@ -1,429 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#include "nsVersionComparator.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#if defined(_WIN32) && !defined(UPDATER_NO_STRING_GLUE_STL)
-#include <wchar.h>
-#include "Char16.h"
-#endif
-
-#ifdef _WIN32
-// from Mozilla's nsAlgorithm.h
-template <class T> inline const T& XPCOM_MIN(const T& aA, const T& aB) { return aB < aA ? aB : aA; }
-#endif
-
-struct VersionPart
-{
- int32_t numA;
-
- const char* strB; // NOT null-terminated, can be a null pointer
- uint32_t strBlen;
-
- int32_t numC;
-
- char* extraD; // null-terminated
-};
-
-#ifdef _WIN32
-struct VersionPartW
-{
- int32_t numA;
-
- wchar_t* strB; // NOT null-terminated, can be a null pointer
- uint32_t strBlen;
-
- int32_t numC;
-
- wchar_t* extraD; // null-terminated
-};
-#endif
-
-/**
- * Parse a version part into a number and "extra text".
- *
- * @returns A pointer to the next versionpart, or null if none.
- */
-static char* ParseVP(char* aPart, VersionPart& aResult)
-{
- char* dot;
-
- aResult.numA = 0;
- aResult.strB = nullptr;
- aResult.strBlen = 0;
- aResult.numC = 0;
- aResult.extraD = nullptr;
-
- if (!aPart)
- {
- return aPart;
- }
-
- dot = strchr(aPart, '.');
- if (dot)
- {
- *dot = '\0';
- }
-
- if (aPart[0] == '*' && aPart[1] == '\0')
- {
- aResult.numA = INT32_MAX;
- aResult.strB = "";
- }
- else
- {
- aResult.numA = strtol(aPart, const_cast<char**>(&aResult.strB), 10);
- }
-
- if (!*aResult.strB)
- {
- aResult.strB = nullptr;
- aResult.strBlen = 0;
- }
- else
- {
- if (aResult.strB[0] == '+')
- {
- static const char kPre[] = "pre";
-
- ++aResult.numA;
- aResult.strB = kPre;
- aResult.strBlen = sizeof(kPre) - 1;
- }
- else
- {
- const char* numstart = strpbrk(aResult.strB, "0123456789+-");
- if (!numstart)
- {
- aResult.strBlen = strlen(aResult.strB);
- }
- else
- {
- aResult.strBlen = numstart - aResult.strB;
-
- aResult.numC = strtol(numstart, &aResult.extraD, 10);
- if (!*aResult.extraD)
- {
- aResult.extraD = nullptr;
- }
- }
- }
- }
-
- if (dot)
- {
- ++dot;
-
- if (!*dot)
- {
- dot = nullptr;
- }
- }
-
- return dot;
-}
-
-/**
- * Parse a version part into a number and "extra text".
- *
- * @returns A pointer to the next versionpart, or null if none.
- */
-#ifdef _WIN32
-static wchar_t* ParseVP(wchar_t* aPart, VersionPartW& aResult)
-{
- wchar_t* dot;
-
- aResult.numA = 0;
- aResult.strB = nullptr;
- aResult.strBlen = 0;
- aResult.numC = 0;
- aResult.extraD = nullptr;
-
- if (!aPart)
- {
- return aPart;
- }
-
- dot = wcschr(aPart, '.');
- if (dot)
- {
- *dot = '\0';
- }
-
- if (aPart[0] == '*' && aPart[1] == '\0')
- {
- aResult.numA = INT32_MAX;
- aResult.strB = L"";
- }
- else
- {
- aResult.numA = wcstol(aPart, const_cast<wchar_t**>(&aResult.strB), 10);
- }
-
- if (!*aResult.strB)
- {
- aResult.strB = nullptr;
- aResult.strBlen = 0;
- }
- else
- {
- if (aResult.strB[0] == '+')
- {
- static wchar_t kPre[] = L"pre";
-
- ++aResult.numA;
- aResult.strB = kPre;
- aResult.strBlen = sizeof(kPre) - 1;
- }
- else
- {
- const wchar_t* numstart = wcspbrk(aResult.strB, L"0123456789+-");
- if (!numstart)
- {
- aResult.strBlen = wcslen(aResult.strB);
- }
- else
- {
- aResult.strBlen = numstart - aResult.strB;
-
- aResult.numC = wcstol(numstart, &aResult.extraD, 10);
- if (!*aResult.extraD)
- {
- aResult.extraD = nullptr;
- }
- }
- }
- }
-
- if (dot)
- {
- ++dot;
-
- if (!*dot)
- {
- dot = nullptr;
- }
- }
-
- return dot;
-}
-#endif
-
-// compare two null-terminated strings, which may be null pointers
-static int32_t ns_strcmp(const char* aStr1, const char* aStr2)
-{
- // any string is *before* no string
- if (!aStr1)
- {
- return aStr2 != 0;
- }
-
- if (!aStr2)
- {
- return -1;
- }
-
- return strcmp(aStr1, aStr2);
-}
-
-// compare two length-specified string, which may be null pointers
-static int32_t ns_strnncmp(const char* aStr1, uint32_t aLen1, const char* aStr2, uint32_t aLen2)
-{
- // any string is *before* no string
- if (!aStr1)
- {
- return aStr2 != 0;
- }
-
- if (!aStr2)
- {
- return -1;
- }
-
- for (; aLen1 && aLen2; --aLen1, --aLen2, ++aStr1, ++aStr2)
- {
- if (*aStr1 < *aStr2)
- {
- return -1;
- }
-
- if (*aStr1 > *aStr2)
- {
- return 1;
- }
- }
-
- if (aLen1 == 0)
- {
- return aLen2 == 0 ? 0 : -1;
- }
-
- return 1;
-}
-
-// compare two int32_t
-static int32_t ns_cmp(int32_t aNum1, int32_t aNum2)
-{
- if (aNum1 < aNum2)
- {
- return -1;
- }
-
- return aNum1 != aNum2;
-}
-
-/**
- * Compares two VersionParts
- */
-static int32_t CompareVP(VersionPart& aVer1, VersionPart& aVer2)
-{
- int32_t r = ns_cmp(aVer1.numA, aVer2.numA);
- if (r)
- {
- return r;
- }
-
- r = ns_strnncmp(aVer1.strB, aVer1.strBlen, aVer2.strB, aVer2.strBlen);
- if (r)
- {
- return r;
- }
-
- r = ns_cmp(aVer1.numC, aVer2.numC);
- if (r)
- {
- return r;
- }
-
- return ns_strcmp(aVer1.extraD, aVer2.extraD);
-}
-
-/**
- * Compares two VersionParts
- */
-#ifdef _WIN32
-static int32_t CompareVP(VersionPartW& aVer1, VersionPartW& aVer2)
-{
- int32_t r = ns_cmp(aVer1.numA, aVer2.numA);
- if (r)
- {
- return r;
- }
-
- r = wcsncmp(aVer1.strB, aVer2.strB, XPCOM_MIN(aVer1.strBlen, aVer2.strBlen));
- if (r)
- {
- return r;
- }
-
- r = ns_cmp(aVer1.numC, aVer2.numC);
- if (r)
- {
- return r;
- }
-
- if (!aVer1.extraD)
- {
- return aVer2.extraD != 0;
- }
-
- if (!aVer2.extraD)
- {
- return -1;
- }
-
- return wcscmp(aVer1.extraD, aVer2.extraD);
-}
-#endif
-
-namespace mozilla
-{
-#ifdef _WIN32
-int32_t CompareVersions(const wchar_t* aStrA, const wchar_t* aStrB)
-{
- wchar_t* A2 = wcsdup(aStrA);
- if (!A2)
- {
- return 1;
- }
-
- wchar_t* B2 = wcsdup(aStrB);
- if (!B2)
- {
- free(A2);
- return 1;
- }
-
- int32_t result;
- wchar_t* a = A2;
- wchar_t* b = B2;
-
- do
- {
- VersionPartW va, vb;
-
- a = ParseVP(a, va);
- b = ParseVP(b, vb);
-
- result = CompareVP(va, vb);
- if (result)
- {
- break;
- }
-
- } while (a || b);
-
- free(A2);
- free(B2);
-
- return result;
-}
-#endif
-
-int32_t CompareVersions(const char* aStrA, const char* aStrB)
-{
- char* A2 = strdup(aStrA);
- if (!A2)
- {
- return 1;
- }
-
- char* B2 = strdup(aStrB);
- if (!B2)
- {
- free(A2);
- return 1;
- }
-
- int32_t result;
- char* a = A2;
- char* b = B2;
-
- do
- {
- VersionPart va, vb;
-
- a = ParseVP(a, va);
- b = ParseVP(b, vb);
-
- result = CompareVP(va, vb);
- if (result)
- {
- break;
- }
-
- } while (a || b);
-
- free(A2);
- free(B2);
-
- return result;
-}
-
-} // namespace mozilla
diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h
deleted file mode 100644
index d793e345eb86..000000000000
--- a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 nsVersionComparator_h__
-#define nsVersionComparator_h__
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#if defined(_WIN32) && !defined(UPDATER_NO_STRING_GLUE_STL)
-#include <wchar.h>
-#include <stdint.h>
-
-#endif
-
-/**
- * In order to compare version numbers in Mozilla, you need to use the
- * mozilla::Version class. You can construct an object of this type by passing
- * in a string version number to the constructor. Objects of this type can be
- * compared using the standard comparison operators.
- *
- * For example, let's say that you want to make sure that a given version
- * number is not older than 15.a2. Here's how you would write a function to
- * do that.
- *
- * bool IsVersionValid(const char* version) {
- * return mozilla::Version("15.a2") <= mozilla::Version(version);
- * }
- *
- * Or, since Version's constructor is implicit, you can simplify this code:
- *
- * bool IsVersionValid(const char* version) {
- * return mozilla::Version("15.a2") <= version;
- * }
- *
- * On Windows, if your version strings are wide characters, you should use the
- * mozilla::VersionW variant instead. The semantics of that class is the same
- * as Version.
- */
-
-namespace mozilla {
-
-int32_t CompareVersions(const char* aStrA, const char* aStrB);
-
-#ifdef _WIN32
-int32_t CompareVersions(const wchar_t* aStrA, const wchar_t* aStrB);
-#endif
-
-struct Version
-{
- explicit Version(const char* aVersionString)
- {
- versionContent = strdup(aVersionString);
- }
-
- const char* ReadContent() const
- {
- return versionContent;
- }
-
- ~Version()
- {
- free(versionContent);
- }
-
- bool operator<(const Version& aRhs) const
- {
- return CompareVersions(versionContent, aRhs.ReadContent()) == -1;
- }
- bool operator<=(const Version& aRhs) const
- {
- return CompareVersions(versionContent, aRhs.ReadContent()) < 1;
- }
- bool operator>(const Version& aRhs) const
- {
- return CompareVersions(versionContent, aRhs.ReadContent()) == 1;
- }
- bool operator>=(const Version& aRhs) const
- {
- return CompareVersions(versionContent, aRhs.ReadContent()) > -1;
- }
- bool operator==(const Version& aRhs) const
- {
- return CompareVersions(versionContent, aRhs.ReadContent()) == 0;
- }
- bool operator!=(const Version& aRhs) const
- {
- return CompareVersions(versionContent, aRhs.ReadContent()) != 0;
- }
- bool operator<(const char* aRhs) const
- {
- return CompareVersions(versionContent, aRhs) == -1;
- }
- bool operator<=(const char* aRhs) const
- {
- return CompareVersions(versionContent, aRhs) < 1;
- }
- bool operator>(const char* aRhs) const
- {
- return CompareVersions(versionContent, aRhs) == 1;
- }
- bool operator>=(const char* aRhs) const
- {
- return CompareVersions(versionContent, aRhs) > -1;
- }
- bool operator==(const char* aRhs) const
- {
- return CompareVersions(versionContent, aRhs) == 0;
- }
- bool operator!=(const char* aRhs) const
- {
- return CompareVersions(versionContent, aRhs) != 0;
- }
-
-private:
- char* versionContent;
-};
-
-#ifdef _WIN32
-struct VersionW
-{
- explicit VersionW(const wchar_t* aVersionStringW)
- {
- versionContentW =
- reinterpret_cast<wchar_t*>(wcsdup(aVersionStringW));
- }
-
- const wchar_t* ReadContentW() const
- {
- return versionContentW;
- }
-
- ~VersionW()
- {
- free(versionContentW);
- }
-
- bool operator<(const VersionW& aRhs) const
- {
- return CompareVersions(versionContentW, aRhs.ReadContentW()) == -1;
- }
- bool operator<=(const VersionW& aRhs) const
- {
- return CompareVersions(versionContentW, aRhs.ReadContentW()) < 1;
- }
- bool operator>(const VersionW& aRhs) const
- {
- return CompareVersions(versionContentW, aRhs.ReadContentW()) == 1;
- }
- bool operator>=(const VersionW& aRhs) const
- {
- return CompareVersions(versionContentW, aRhs.ReadContentW()) > -1;
- }
- bool operator==(const VersionW& aRhs) const
- {
- return CompareVersions(versionContentW, aRhs.ReadContentW()) == 0;
- }
- bool operator!=(const VersionW& aRhs) const
- {
- return CompareVersions(versionContentW, aRhs.ReadContentW()) != 0;
- }
-
-private:
- wchar_t* versionContentW;
-};
-#endif
-
-} // namespace mozilla
-
-#endif // nsVersionComparator_h__
-