From 6b4f081fdf3e11e27c955ab304ea602353b57110 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 15 Jan 2016 17:40:12 +0100 Subject: [PATCH] dos2unix the updater --- updater/main.cpp | 208 ++++----- updater/update.cpp | 286 ++++++------ updater/update.h | 120 ++--- updater/updater.pro | 80 ++-- updater/widget.cpp | 676 +++++++++++++-------------- updater/widget.h | 134 +++--- updater/widget.ui | 278 +++++------ updater/windows/updater.exe.manifest | 22 +- updater/windows/updater.rc | 2 +- 9 files changed, 903 insertions(+), 903 deletions(-) diff --git a/updater/main.cpp b/updater/main.cpp index 6688f98c1..68067a60b 100644 --- a/updater/main.cpp +++ b/updater/main.cpp @@ -1,104 +1,104 @@ -/* - Copyright © 2014 by The qTox Project - - This file is part of qTox, a Qt-based graphical interface for Tox. - - qTox is libre software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - qTox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with qTox. If not, see -*/ - - -#include "widget.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static std::unique_ptr logFileStream {nullptr}; -static std::unique_ptr logFileFile {nullptr}; -static QMutex mutex; - -void logMessageHandler(QtMsgType type, const QMessageLogContext& ctxt, const QString& msg) -{ - // Silence qWarning spam due to bug in QTextBrowser (trying to open a file for base64 images) - if (ctxt.function == QString("virtual bool QFSFileEngine::open(QIODevice::OpenMode)") - && msg == QString("QFSFileEngine::open: No file name specified")) - return; - - QString LogMsg = QString("[%1] %2:%3 : ") - .arg(QTime::currentTime().toString("HH:mm:ss.zzz")).arg(ctxt.file).arg(ctxt.line); - switch (type) - { - case QtDebugMsg: - LogMsg += "Debug"; - break; - case QtWarningMsg: - LogMsg += "Warning"; - break; - case QtCriticalMsg: - LogMsg += "Critical"; - break; - case QtFatalMsg: - LogMsg += "Fatal"; - break; - default: - break; - } - - LogMsg += ": " + msg + "\n"; - - QTextStream out(stderr, QIODevice::WriteOnly); - out << LogMsg; - - if (!logFileStream) - return; - - QMutexLocker locker(&mutex); - *logFileStream << LogMsg; - logFileStream->flush(); -} - -int main(int argc, char *argv[]) -{ - qInstallMessageHandler(logMessageHandler); - QApplication a(argc, argv); - - logFileStream.reset(new QTextStream); - logFileFile.reset(new QFile(QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QDir::separator() - + "AppData" + QDir::separator() + "Roaming" + QDir::separator() + "tox")+QDir::separator()+"qtox.log")); - if (logFileFile->open(QIODevice::Append)) - { - logFileStream->setDevice(logFileFile.get()); - *logFileStream << QDateTime::currentDateTime().toString("\nyyyy-MM-dd HH:mm:ss' Updater file logger starting\n'"); - } - else - { - qWarning() << "Couldn't open log file!\n"; - logFileStream.release(); - } - - long unsigned int bufsize=100; - char buf[100]; - GetUserNameA(buf, &bufsize); - qDebug() << "Updater running as user" << buf; - - Widget w; - w.show(); - - return a.exec(); -} +/* + Copyright © 2014 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see +*/ + + +#include "widget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static std::unique_ptr logFileStream {nullptr}; +static std::unique_ptr logFileFile {nullptr}; +static QMutex mutex; + +void logMessageHandler(QtMsgType type, const QMessageLogContext& ctxt, const QString& msg) +{ + // Silence qWarning spam due to bug in QTextBrowser (trying to open a file for base64 images) + if (ctxt.function == QString("virtual bool QFSFileEngine::open(QIODevice::OpenMode)") + && msg == QString("QFSFileEngine::open: No file name specified")) + return; + + QString LogMsg = QString("[%1] %2:%3 : ") + .arg(QTime::currentTime().toString("HH:mm:ss.zzz")).arg(ctxt.file).arg(ctxt.line); + switch (type) + { + case QtDebugMsg: + LogMsg += "Debug"; + break; + case QtWarningMsg: + LogMsg += "Warning"; + break; + case QtCriticalMsg: + LogMsg += "Critical"; + break; + case QtFatalMsg: + LogMsg += "Fatal"; + break; + default: + break; + } + + LogMsg += ": " + msg + "\n"; + + QTextStream out(stderr, QIODevice::WriteOnly); + out << LogMsg; + + if (!logFileStream) + return; + + QMutexLocker locker(&mutex); + *logFileStream << LogMsg; + logFileStream->flush(); +} + +int main(int argc, char *argv[]) +{ + qInstallMessageHandler(logMessageHandler); + QApplication a(argc, argv); + + logFileStream.reset(new QTextStream); + logFileFile.reset(new QFile(QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QDir::separator() + + "AppData" + QDir::separator() + "Roaming" + QDir::separator() + "tox")+QDir::separator()+"qtox.log")); + if (logFileFile->open(QIODevice::Append)) + { + logFileStream->setDevice(logFileFile.get()); + *logFileStream << QDateTime::currentDateTime().toString("\nyyyy-MM-dd HH:mm:ss' Updater file logger starting\n'"); + } + else + { + qWarning() << "Couldn't open log file!\n"; + logFileStream.release(); + } + + long unsigned int bufsize=100; + char buf[100]; + GetUserNameA(buf, &bufsize); + qDebug() << "Updater running as user" << buf; + + Widget w; + w.show(); + + return a.exec(); +} diff --git a/updater/update.cpp b/updater/update.cpp index 6e6e4d47b..4cd0b8978 100644 --- a/updater/update.cpp +++ b/updater/update.cpp @@ -1,143 +1,143 @@ -/* - Copyright © 2014 by The qTox Project - - This file is part of qTox, a Qt-based graphical interface for Tox. - - qTox is libre software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - qTox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with qTox. If not, see -*/ - - -#include "update.h" -#include "serialize.h" -#include "widget.h" -#include -#include -#include -#include -#include - -unsigned char key[crypto_sign_PUBLICKEYBYTES] = -{ - 0x20, 0x89, 0x39, 0xaa, 0x9a, 0xe8, 0xb5, 0x21, 0x0e, 0xac, 0x02, 0xa9, 0xc4, 0x92, 0xd9, 0xa2, - 0x17, 0x83, 0xbd, 0x78, 0x0a, 0xda, 0x33, 0xcd, 0xa5, 0xc6, 0x44, 0xc7, 0xfc, 0xed, 0x00, 0x13 -}; - -QByteArray getLocalFlist() -{ - QByteArray flist; - - QFile flistFile("flist"); - if (!flistFile.open(QIODevice::ReadOnly)) - { - qWarning() << "getLocalFlist: Can't open local flist"; - return flist; - } - - flist = flistFile.readAll(); - flistFile.close(); - - return flist; -} - -bool isUpToDate(UpdateFileMeta fileMeta) -{ - QString appDir = qApp->applicationDirPath(); - QFile file(appDir+QDir::separator()+fileMeta.installpath); - if (!file.open(QIODevice::ReadOnly)) - return false; - - // If the data we have is corrupted or old, mark it for update - QByteArray data = file.readAll(); - if (crypto_sign_verify_detached(fileMeta.sig, (unsigned char*)data.data(), data.size(), key) != 0) - return false; - - return true; -} - -QList genUpdateDiff(QList updateFlist, Widget* w) -{ - QList diff; - - float progressDiff = 45; - float progress = 5; - - for (UpdateFileMeta file : updateFlist) - { - if (!isUpToDate(file)) - diff += file; - progress += progressDiff / updateFlist.size(); - w->setProgress(progress); - } - - return diff; -} - -QList parseFlist(QByteArray flistData) -{ - QList flist; - - if (flistData.isEmpty()) - { - qWarning() << "AutoUpdater::parseflist: Empty data"; - return flist; - } - - // Check version - if (flistData[0] != '1') - { - qWarning() << "AutoUpdater: parseflist: Bad version "<<(uint8_t)flistData[0]; - return flist; - } - flistData = flistData.mid(1); - - // Check signature - if (flistData.size() < (int)(crypto_sign_BYTES)) - { - qWarning() << "AutoUpdater::parseflist: Truncated data"; - return flist; - } - else - { - QByteArray msgData = flistData.mid(crypto_sign_BYTES); - unsigned char* msg = (unsigned char*)msgData.data(); - if (crypto_sign_verify_detached((unsigned char*)flistData.data(), msg, msgData.size(), key) != 0) - { - qCritical() << "AutoUpdater: parseflist: FORGED FLIST FILE"; - return flist; - } - flistData = flistData.mid(crypto_sign_BYTES); - } - - // Parse. We assume no errors handling needed since the signature is valid. - while (!flistData.isEmpty()) - { - UpdateFileMeta newFile; - - memcpy(newFile.sig, flistData.data(), crypto_sign_BYTES); - flistData = flistData.mid(crypto_sign_BYTES); - - newFile.id = dataToString(flistData); - flistData = flistData.mid(newFile.id.size() + getVUint32Size(flistData)); - - newFile.installpath = dataToString(flistData); - flistData = flistData.mid(newFile.installpath.size() + getVUint32Size(flistData)); - - newFile.size = dataToUint64(flistData); - flistData = flistData.mid(8); - - flist += newFile; - } - - return flist; -} +/* + Copyright © 2014 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see +*/ + + +#include "update.h" +#include "serialize.h" +#include "widget.h" +#include +#include +#include +#include +#include + +unsigned char key[crypto_sign_PUBLICKEYBYTES] = +{ + 0x20, 0x89, 0x39, 0xaa, 0x9a, 0xe8, 0xb5, 0x21, 0x0e, 0xac, 0x02, 0xa9, 0xc4, 0x92, 0xd9, 0xa2, + 0x17, 0x83, 0xbd, 0x78, 0x0a, 0xda, 0x33, 0xcd, 0xa5, 0xc6, 0x44, 0xc7, 0xfc, 0xed, 0x00, 0x13 +}; + +QByteArray getLocalFlist() +{ + QByteArray flist; + + QFile flistFile("flist"); + if (!flistFile.open(QIODevice::ReadOnly)) + { + qWarning() << "getLocalFlist: Can't open local flist"; + return flist; + } + + flist = flistFile.readAll(); + flistFile.close(); + + return flist; +} + +bool isUpToDate(UpdateFileMeta fileMeta) +{ + QString appDir = qApp->applicationDirPath(); + QFile file(appDir+QDir::separator()+fileMeta.installpath); + if (!file.open(QIODevice::ReadOnly)) + return false; + + // If the data we have is corrupted or old, mark it for update + QByteArray data = file.readAll(); + if (crypto_sign_verify_detached(fileMeta.sig, (unsigned char*)data.data(), data.size(), key) != 0) + return false; + + return true; +} + +QList genUpdateDiff(QList updateFlist, Widget* w) +{ + QList diff; + + float progressDiff = 45; + float progress = 5; + + for (UpdateFileMeta file : updateFlist) + { + if (!isUpToDate(file)) + diff += file; + progress += progressDiff / updateFlist.size(); + w->setProgress(progress); + } + + return diff; +} + +QList parseFlist(QByteArray flistData) +{ + QList flist; + + if (flistData.isEmpty()) + { + qWarning() << "AutoUpdater::parseflist: Empty data"; + return flist; + } + + // Check version + if (flistData[0] != '1') + { + qWarning() << "AutoUpdater: parseflist: Bad version "<<(uint8_t)flistData[0]; + return flist; + } + flistData = flistData.mid(1); + + // Check signature + if (flistData.size() < (int)(crypto_sign_BYTES)) + { + qWarning() << "AutoUpdater::parseflist: Truncated data"; + return flist; + } + else + { + QByteArray msgData = flistData.mid(crypto_sign_BYTES); + unsigned char* msg = (unsigned char*)msgData.data(); + if (crypto_sign_verify_detached((unsigned char*)flistData.data(), msg, msgData.size(), key) != 0) + { + qCritical() << "AutoUpdater: parseflist: FORGED FLIST FILE"; + return flist; + } + flistData = flistData.mid(crypto_sign_BYTES); + } + + // Parse. We assume no errors handling needed since the signature is valid. + while (!flistData.isEmpty()) + { + UpdateFileMeta newFile; + + memcpy(newFile.sig, flistData.data(), crypto_sign_BYTES); + flistData = flistData.mid(crypto_sign_BYTES); + + newFile.id = dataToString(flistData); + flistData = flistData.mid(newFile.id.size() + getVUint32Size(flistData)); + + newFile.installpath = dataToString(flistData); + flistData = flistData.mid(newFile.installpath.size() + getVUint32Size(flistData)); + + newFile.size = dataToUint64(flistData); + flistData = flistData.mid(8); + + flist += newFile; + } + + return flist; +} diff --git a/updater/update.h b/updater/update.h index 13f8db17a..436d6f7d3 100644 --- a/updater/update.h +++ b/updater/update.h @@ -1,60 +1,60 @@ -/* - Copyright © 2014 by The qTox Project - - This file is part of qTox, a Qt-based graphical interface for Tox. - - qTox is libre software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - qTox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with qTox. If not, see -*/ - - -#ifndef UPDATE_H -#define UPDATE_H - -#include -#include -#include - -class Widget; - -struct UpdateFileMeta -{ - unsigned char sig[crypto_sign_BYTES]; ///< Signature of the file (ed25519) - QString id; ///< Unique id of the file - QString installpath; ///< Local path including the file name. May be relative to qtox-updater or absolute - uint64_t size; ///< Size in bytes of the file - - bool operator==(const UpdateFileMeta& other) - { - return (size == other.size - && id == other.id && installpath == other.installpath - && memcmp(sig, other.sig, crypto_sign_BYTES) == 0); - } -}; - -struct UpdateFile -{ - UpdateFileMeta metadata; - QByteArray data; -}; - -/// Gets the local flist. Returns an empty array on error -QByteArray getLocalFlist(); -/// Parses and validates a flist file. Returns an empty list on error -QList parseFlist(QByteArray flistData); -/// Generates a list of files we need to update -QList genUpdateDiff(QList updateFlist, Widget *w); - -extern unsigned char key[crypto_sign_PUBLICKEYBYTES]; - -#endif // UPDATE_H +/* + Copyright © 2014 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see +*/ + + +#ifndef UPDATE_H +#define UPDATE_H + +#include +#include +#include + +class Widget; + +struct UpdateFileMeta +{ + unsigned char sig[crypto_sign_BYTES]; ///< Signature of the file (ed25519) + QString id; ///< Unique id of the file + QString installpath; ///< Local path including the file name. May be relative to qtox-updater or absolute + uint64_t size; ///< Size in bytes of the file + + bool operator==(const UpdateFileMeta& other) + { + return (size == other.size + && id == other.id && installpath == other.installpath + && memcmp(sig, other.sig, crypto_sign_BYTES) == 0); + } +}; + +struct UpdateFile +{ + UpdateFileMeta metadata; + QByteArray data; +}; + +/// Gets the local flist. Returns an empty array on error +QByteArray getLocalFlist(); +/// Parses and validates a flist file. Returns an empty list on error +QList parseFlist(QByteArray flistData); +/// Generates a list of files we need to update +QList genUpdateDiff(QList updateFlist, Widget *w); + +extern unsigned char key[crypto_sign_PUBLICKEYBYTES]; + +#endif // UPDATE_H diff --git a/updater/updater.pro b/updater/updater.pro index 5373d1a72..c52a12459 100644 --- a/updater/updater.pro +++ b/updater/updater.pro @@ -1,40 +1,40 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2014-11-09T21:09:08 -# -#------------------------------------------------- - -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = qtox-updater -TEMPLATE = app - -CONFIG += c++11 - -QMAKE_CXXFLAGS += -fno-exceptions - -SOURCES += main.cpp\ - widget.cpp \ - update.cpp \ - serialize.cpp - -HEADERS += widget.h \ - update.h \ - serialize.h - -FORMS += widget.ui - -RESOURCES += \ - res.qrc - -INCLUDEPATH += libs/include - -RC_FILE = windows/updater.rc - -LIBS += -L$$PWD/libs/lib/ -lsodium - -win32 { - LIBS += -lshell32 -luuid -} +#------------------------------------------------- +# +# Project created by QtCreator 2014-11-09T21:09:08 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = qtox-updater +TEMPLATE = app + +CONFIG += c++11 + +QMAKE_CXXFLAGS += -fno-exceptions + +SOURCES += main.cpp\ + widget.cpp \ + update.cpp \ + serialize.cpp + +HEADERS += widget.h \ + update.h \ + serialize.h + +FORMS += widget.ui + +RESOURCES += \ + res.qrc + +INCLUDEPATH += libs/include + +RC_FILE = windows/updater.rc + +LIBS += -L$$PWD/libs/lib/ -lsodium + +win32 { + LIBS += -lshell32 -luuid +} diff --git a/updater/widget.cpp b/updater/widget.cpp index bb3a86aa8..7ea863c46 100644 --- a/updater/widget.cpp +++ b/updater/widget.cpp @@ -1,338 +1,338 @@ -/* - Copyright © 2014 by The qTox Project - - This file is part of qTox, a Qt-based graphical interface for Tox. - - qTox is libre software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - qTox is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with qTox. If not, see -*/ - - -#include "widget.h" -#include "ui_widget.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "update.h" - -#ifdef Q_OS_WIN -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 // Vista for SHGetKnownFolderPath -#include -#include -#include -#include - -const bool supported = true; -const QString QTOX_PATH = "qtox.exe"; -#else -const bool supported = false; -const QString QTOX_PATH; -#endif -const QString SETTINGS_FILE = "settings.ini"; - -Widget::Widget(QWidget *parent) : - QWidget(parent), - ui(new Ui::Widget) -{ - ui->setupUi(this); - - // Updates only for supported platforms - if (!supported) - fatalError(tr("The qTox updater is not supported on this platform.")); - -#ifdef Q_OS_WIN - // Get a primary unelevated token of the actual user - hPrimaryToken = nullptr; - HANDLE hShellProcess = nullptr, hShellProcessToken = nullptr; - const DWORD dwTokenRights = TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_ASSIGN_PRIMARY - | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID; - DWORD dwPID = 0; - HWND hwnd = nullptr; - DWORD dwLastErr = 0; - - // Enable SeIncreaseQuotaPrivilege - HANDLE hProcessToken = NULL; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcessToken)) - goto unelevateFail; - TOKEN_PRIVILEGES tkp; - tkp.PrivilegeCount = 1; - LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid); - tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - AdjustTokenPrivileges(hProcessToken, FALSE, &tkp, 0, NULL, NULL); - dwLastErr = GetLastError(); - CloseHandle(hProcessToken); - if (ERROR_SUCCESS != dwLastErr) - goto unelevateFail; - - // Get a primary copy of the desktop shell's token, - // we're assuming the shell is running as the actual user - hwnd = GetShellWindow(); - if (!hwnd) - goto unelevateFail; - GetWindowThreadProcessId(hwnd, &dwPID); - if (!dwPID) - goto unelevateFail; - hShellProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID); - if (!hShellProcess) - goto unelevateFail; - if (!OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, &hShellProcessToken)) - goto unelevateFail; - - // Duplicate the shell's process token to get a primary token. - // Based on experimentation, this is the minimal set of rights required for CreateProcessWithTokenW (contrary to current documentation). - if (!DuplicateTokenEx(hShellProcessToken, dwTokenRights, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken)) - goto unelevateFail; - - qDebug() << "Unelevated primary access token acquired"; - goto unelevateCleanup; -unelevateFail: - qWarning() << "Unelevate failed, couldn't get access token"; -unelevateCleanup: - CloseHandle(hShellProcessToken); - CloseHandle(hShellProcess); -#endif - - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); -} - -Widget::~Widget() -{ -#ifdef Q_OS_WIN - CloseHandle(hPrimaryToken); -#endif - delete ui; -} - -void Widget::setProgress(int value) -{ - ui->progress->setValue(value); - ui->progress->repaint(); - qApp->processEvents(); -} - -void Widget::fatalError(QString message) -{ - qCritical() << "Update aborted with error:"< updateFlist = parseFlist(updateFlistData); - setProgress(5); - - /// 2. Generate a diff (5-50%) - QList diff = genUpdateDiff(updateFlist, this); - for (UpdateFileMeta fileMeta : diff) - if (!QFile::exists(updateDirStr+fileMeta.installpath)) - fatalError(tr("The update is incomplete.")); - - if (diff.size() == 0) - fatalError(tr("The update is empty!")); - setProgress(50); - qDebug() << "Diff generated,"< +*/ + + +#include "widget.h" +#include "ui_widget.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "update.h" + +#ifdef Q_OS_WIN +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 // Vista for SHGetKnownFolderPath +#include +#include +#include +#include + +const bool supported = true; +const QString QTOX_PATH = "qtox.exe"; +#else +const bool supported = false; +const QString QTOX_PATH; +#endif +const QString SETTINGS_FILE = "settings.ini"; + +Widget::Widget(QWidget *parent) : + QWidget(parent), + ui(new Ui::Widget) +{ + ui->setupUi(this); + + // Updates only for supported platforms + if (!supported) + fatalError(tr("The qTox updater is not supported on this platform.")); + +#ifdef Q_OS_WIN + // Get a primary unelevated token of the actual user + hPrimaryToken = nullptr; + HANDLE hShellProcess = nullptr, hShellProcessToken = nullptr; + const DWORD dwTokenRights = TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_ASSIGN_PRIMARY + | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID; + DWORD dwPID = 0; + HWND hwnd = nullptr; + DWORD dwLastErr = 0; + + // Enable SeIncreaseQuotaPrivilege + HANDLE hProcessToken = NULL; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcessToken)) + goto unelevateFail; + TOKEN_PRIVILEGES tkp; + tkp.PrivilegeCount = 1; + LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid); + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hProcessToken, FALSE, &tkp, 0, NULL, NULL); + dwLastErr = GetLastError(); + CloseHandle(hProcessToken); + if (ERROR_SUCCESS != dwLastErr) + goto unelevateFail; + + // Get a primary copy of the desktop shell's token, + // we're assuming the shell is running as the actual user + hwnd = GetShellWindow(); + if (!hwnd) + goto unelevateFail; + GetWindowThreadProcessId(hwnd, &dwPID); + if (!dwPID) + goto unelevateFail; + hShellProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID); + if (!hShellProcess) + goto unelevateFail; + if (!OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, &hShellProcessToken)) + goto unelevateFail; + + // Duplicate the shell's process token to get a primary token. + // Based on experimentation, this is the minimal set of rights required for CreateProcessWithTokenW (contrary to current documentation). + if (!DuplicateTokenEx(hShellProcessToken, dwTokenRights, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken)) + goto unelevateFail; + + qDebug() << "Unelevated primary access token acquired"; + goto unelevateCleanup; +unelevateFail: + qWarning() << "Unelevate failed, couldn't get access token"; +unelevateCleanup: + CloseHandle(hShellProcessToken); + CloseHandle(hShellProcess); +#endif + + QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); +} + +Widget::~Widget() +{ +#ifdef Q_OS_WIN + CloseHandle(hPrimaryToken); +#endif + delete ui; +} + +void Widget::setProgress(int value) +{ + ui->progress->setValue(value); + ui->progress->repaint(); + qApp->processEvents(); +} + +void Widget::fatalError(QString message) +{ + qCritical() << "Update aborted with error:"< updateFlist = parseFlist(updateFlistData); + setProgress(5); + + /// 2. Generate a diff (5-50%) + QList diff = genUpdateDiff(updateFlist, this); + for (UpdateFileMeta fileMeta : diff) + if (!QFile::exists(updateDirStr+fileMeta.installpath)) + fatalError(tr("The update is incomplete.")); + + if (diff.size() == 0) + fatalError(tr("The update is empty!")); + setProgress(50); + qDebug() << "Diff generated,"< -*/ - - -#ifndef WIDGET_H -#define WIDGET_H - -#include - -#ifdef Q_OS_WIN -#include -#endif - -namespace Ui { -class Widget; -} - -class Widget : public QWidget -{ - Q_OBJECT - -public: - explicit Widget(QWidget *parent = 0); - ~Widget(); - - // Utilities - void deleteBackups(); - void restoreBackups(); - void setProgress(int value); - QString getSettingsDirPath(); - bool isToxPortableEnabled(); - - // Noreturn - void fatalError(QString message); ///< Calls deleteUpdate and startQToxAndExit - void deleteUpdate(); - void startQToxAndExit(); - -public slots: - // Finds and applies the update - void update(); - -private: - Ui::Widget *ui; - QStringList backups; - -#ifdef Q_OS_WIN - HANDLE hPrimaryToken; -#endif -}; - -#endif // WIDGET_H +/* + Copyright © 2014 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see +*/ + + +#ifndef WIDGET_H +#define WIDGET_H + +#include + +#ifdef Q_OS_WIN +#include +#endif + +namespace Ui { +class Widget; +} + +class Widget : public QWidget +{ + Q_OBJECT + +public: + explicit Widget(QWidget *parent = 0); + ~Widget(); + + // Utilities + void deleteBackups(); + void restoreBackups(); + void setProgress(int value); + QString getSettingsDirPath(); + bool isToxPortableEnabled(); + + // Noreturn + void fatalError(QString message); ///< Calls deleteUpdate and startQToxAndExit + void deleteUpdate(); + void startQToxAndExit(); + +public slots: + // Finds and applies the update + void update(); + +private: + Ui::Widget *ui; + QStringList backups; + +#ifdef Q_OS_WIN + HANDLE hPrimaryToken; +#endif +}; + +#endif // WIDGET_H diff --git a/updater/widget.ui b/updater/widget.ui index b7959ea0b..507ff9f04 100644 --- a/updater/widget.ui +++ b/updater/widget.ui @@ -1,139 +1,139 @@ - - - Widget - - - - 0 - 0 - 401 - 224 - - - - qTox Updater - - - - :/res/qtox-256x256.png:/res/qtox-256x256.png - - - - - 0 - 13 - 191 - 191 - - - - - - - :/res/qtox-256x256.png - - - true - - - - - - 206 - 95 - 171 - 20 - - - - 0 - - - 0 - - - Qt::AlignCenter - - - false - - - - - - 205 - 115 - 171 - 20 - - - - Updating qTox ... - - - Qt::AlignCenter - - - - - - 201 - 170 - 181 - 20 - - - - <html><head/><body><p><a href="https://tox.chat"><span style=" text-decoration: underline; color:#0000ff;">https://tox.chat</span></a></p></body></html> - - - Qt::AlignCenter - - - true - - - - - - 200 - 183 - 181 - 20 - - - - <a href="https://github.com/tux3/qtox">https://github.com/tux3/qtox</a> - - - Qt::AlignCenter - - - - - - 195 - 32 - 191 - 31 - - - - - 14 - - - - qTox Update - - - Qt::AlignCenter - - - - - - - - - + + + Widget + + + + 0 + 0 + 401 + 224 + + + + qTox Updater + + + + :/res/qtox-256x256.png:/res/qtox-256x256.png + + + + + 0 + 13 + 191 + 191 + + + + + + + :/res/qtox-256x256.png + + + true + + + + + + 206 + 95 + 171 + 20 + + + + 0 + + + 0 + + + Qt::AlignCenter + + + false + + + + + + 205 + 115 + 171 + 20 + + + + Updating qTox ... + + + Qt::AlignCenter + + + + + + 201 + 170 + 181 + 20 + + + + <html><head/><body><p><a href="https://tox.chat"><span style=" text-decoration: underline; color:#0000ff;">https://tox.chat</span></a></p></body></html> + + + Qt::AlignCenter + + + true + + + + + + 200 + 183 + 181 + 20 + + + + <a href="https://github.com/tux3/qtox">https://github.com/tux3/qtox</a> + + + Qt::AlignCenter + + + + + + 195 + 32 + 191 + 31 + + + + + 14 + + + + qTox Update + + + Qt::AlignCenter + + + + + + + + + diff --git a/updater/windows/updater.exe.manifest b/updater/windows/updater.exe.manifest index 626d284d9..a6e206c80 100644 --- a/updater/windows/updater.exe.manifest +++ b/updater/windows/updater.exe.manifest @@ -1,12 +1,12 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/updater/windows/updater.rc b/updater/windows/updater.rc index e47abcc22..80d03bd3a 100644 --- a/updater/windows/updater.rc +++ b/updater/windows/updater.rc @@ -1,2 +1,2 @@ -ID_ICON ICON DISCARDABLE "updater.ico" +ID_ICON ICON DISCARDABLE "updater.ico" 1 24 "updater.exe.manifest" \ No newline at end of file