diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /toolkit/mozapps/update/common/updatecommon.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'toolkit/mozapps/update/common/updatecommon.cpp')
-rw-r--r-- | toolkit/mozapps/update/common/updatecommon.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/toolkit/mozapps/update/common/updatecommon.cpp b/toolkit/mozapps/update/common/updatecommon.cpp new file mode 100644 index 000000000..aff7d7260 --- /dev/null +++ b/toolkit/mozapps/update/common/updatecommon.cpp @@ -0,0 +1,213 @@ +/* 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(XP_WIN) +#include <windows.h> +#endif + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> + +#include "updatecommon.h" + +UpdateLog::UpdateLog() : logFP(nullptr) +{ +} + +void UpdateLog::Init(NS_tchar* sourcePath, + const NS_tchar* fileName) +{ + if (logFP) { + return; + } + + int dstFilePathLen = NS_tsnprintf(mDstFilePath, + sizeof(mDstFilePath)/sizeof(mDstFilePath[0]), + NS_T("%s/%s"), sourcePath, fileName); + // If the destination path was over the length limit, + // disable logging by skipping opening the file and setting logFP. + if ((dstFilePathLen > 0) && + (dstFilePathLen < + static_cast<int>(sizeof(mDstFilePath)/sizeof(mDstFilePath[0])))) { +#ifdef XP_WIN + if (GetTempFileNameW(sourcePath, L"log", 0, mTmpFilePath) != 0) { + logFP = NS_tfopen(mTmpFilePath, NS_T("w")); + + // Delete this file now so it is possible to tell from the unelevated + // updater process if the elevated updater process has written the log. + DeleteFileW(mDstFilePath); + } +#elif XP_MACOSX + logFP = NS_tfopen(mDstFilePath, NS_T("w")); +#else + // On platforms that have an updates directory in the installation directory + // (e.g. platforms other than Windows and Mac) the update log is written to + // a temporary file and then to the update log file. This is needed since + // the installation directory is moved during a replace request. This can be + // removed when the platform's updates directory is located outside of the + // installation directory. + logFP = tmpfile(); +#endif + } +} + +void UpdateLog::Finish() +{ + if (!logFP) { + return; + } + +#if !defined(XP_WIN) && !defined(XP_MACOSX) + const int blockSize = 1024; + char buffer[blockSize]; + fflush(logFP); + rewind(logFP); + + FILE *updateLogFP = NS_tfopen(mDstFilePath, NS_T("wb+")); + while (!feof(logFP)) { + size_t read = fread(buffer, 1, blockSize, logFP); + if (ferror(logFP)) { + fclose(logFP); + logFP = nullptr; + fclose(updateLogFP); + updateLogFP = nullptr; + return; + } + + size_t written = 0; + + while (written < read) { + size_t chunkWritten = fwrite(buffer, 1, read - written, updateLogFP); + if (chunkWritten <= 0) { + fclose(logFP); + logFP = nullptr; + fclose(updateLogFP); + updateLogFP = nullptr; + return; + } + + written += chunkWritten; + } + } + fclose(updateLogFP); + updateLogFP = nullptr; +#endif + + fclose(logFP); + logFP = nullptr; + +#ifdef XP_WIN + // When the log file already exists then the elevated updater has already + // written the log file and the temp file for the log should be discarded. + if (!NS_taccess(mDstFilePath, F_OK)) { + DeleteFileW(mTmpFilePath); + } else { + MoveFileW(mTmpFilePath, mDstFilePath); + } +#endif +} + +void UpdateLog::Flush() +{ + if (!logFP) { + return; + } + + fflush(logFP); +} + +void UpdateLog::Printf(const char *fmt, ... ) +{ + if (!logFP) { + return; + } + + va_list ap; + va_start(ap, fmt); + vfprintf(logFP, fmt, ap); + fprintf(logFP, "\n"); + va_end(ap); +} + +void UpdateLog::WarnPrintf(const char *fmt, ... ) +{ + if (!logFP) { + return; + } + + va_list ap; + va_start(ap, fmt); + fprintf(logFP, "*** Warning: "); + vfprintf(logFP, fmt, ap); + fprintf(logFP, "***\n"); + va_end(ap); +} + +/** + * Performs checks of a full path for validity for this application. + * + * @param origFullPath + * The full path to check. + * @return true if the path is valid for this application and false otherwise. + */ +bool +IsValidFullPath(NS_tchar* origFullPath) +{ + // Subtract 1 from MAXPATHLEN for null termination. + if (NS_tstrlen(origFullPath) > MAXPATHLEN - 1) { + // The path is longer than acceptable for this application. + return false; + } + +#ifdef XP_WIN + NS_tchar testPath[MAXPATHLEN] = {NS_T('\0')}; + // GetFullPathNameW will replace / with \ which PathCanonicalizeW requires. + if (GetFullPathNameW(origFullPath, MAXPATHLEN, testPath, nullptr) == 0) { + // Unable to get the full name for the path (e.g. invalid path). + return false; + } + + NS_tchar canonicalPath[MAXPATHLEN] = {NS_T('\0')}; + if (!PathCanonicalizeW(canonicalPath, testPath)) { + // Path could not be canonicalized (e.g. invalid path). + return false; + } + + // Check if the path passed in resolves to a differerent path. + if (NS_tstricmp(origFullPath, canonicalPath) != 0) { + // Case insensitive string comparison between the supplied path and the + // canonical path are not equal. This will prevent directory traversal and + // the use of / in paths since they are converted to \. + return false; + } + + NS_tstrncpy(testPath, origFullPath, MAXPATHLEN); + if (!PathStripToRootW(testPath)) { + // It should always be possible to strip a valid path to its root. + return false; + } + + if (origFullPath[0] == NS_T('\\')) { + // Only allow UNC server share paths. + if (!PathIsUNCServerShareW(testPath)) { + return false; + } + } +#else + // Only allow full paths. + if (origFullPath[0] != NS_T('/')) { + return false; + } + + // The path must not traverse directories + if (NS_tstrstr(origFullPath, NS_T("..")) != nullptr || + NS_tstrstr(origFullPath, NS_T("./")) != nullptr) { + return false; + } +#endif + return true; +} |