mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Merge branch 'autoupdate'
This commit is contained in:
commit
55939e9563
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -8,3 +8,5 @@ Makefile
|
|||
qtox
|
||||
*.qm
|
||||
*.orig
|
||||
build-*-Release
|
||||
build-*-Debug
|
||||
|
|
12
qtox.pro
12
qtox.pro
|
@ -57,7 +57,7 @@ contains(JENKINS,YES) {
|
|||
# Rules for Windows, Mac OSX, and Linux
|
||||
win32 {
|
||||
RC_FILE = windows/qtox.rc
|
||||
LIBS += -liphlpapi -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lvpx -lpthread
|
||||
LIBS += -liphlpapi -L$$PWD/libs/lib -lsodium -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lvpx -lpthread
|
||||
LIBS += -L$$PWD/libs/lib -lopencv_core248 -lopencv_highgui248 -lopencv_imgproc248 -lOpenAL32 -lopus
|
||||
LIBS += -lz -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -ljpeg -ltiff -lpng -ljasper -lIlmImf -lHalf -lws2_32
|
||||
} else {
|
||||
|
@ -76,7 +76,7 @@ win32 {
|
|||
LIBS += -Wl,-Bdynamic -lv4l1 -lv4l2 -lavformat -lavcodec -lavutil -lswscale -lusb-1.0
|
||||
|
||||
} else {
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lvpx -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lvpx -lsodium -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
|
||||
}
|
||||
|
||||
contains(JENKINS, YES) {
|
||||
|
@ -146,7 +146,9 @@ HEADERS += src/widget/form/addfriendform.h \
|
|||
src/ipc.h \
|
||||
src/widget/toxuri.h \
|
||||
src/toxdns.h \
|
||||
src/widget/toxsave.h
|
||||
src/widget/toxsave.h \
|
||||
src/autoupdate.h \
|
||||
src/misc/serialize.h
|
||||
|
||||
SOURCES += \
|
||||
src/widget/form/addfriendform.cpp \
|
||||
|
@ -209,4 +211,6 @@ SOURCES += \
|
|||
src/widget/toxuri.cpp \
|
||||
src/toxdns.cpp \
|
||||
src/ipc.cpp \
|
||||
src/widget/toxsave.cpp
|
||||
src/widget/toxsave.cpp \
|
||||
src/autoupdate.cpp \
|
||||
src/misc/serialize.cpp
|
||||
|
|
414
src/autoupdate.cpp
Normal file
414
src/autoupdate.cpp
Normal file
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "src/autoupdate.h"
|
||||
#include "src/misc/serialize.h"
|
||||
#include "src/misc/settings.h"
|
||||
#include "src/widget/widget.h"
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QMessageBox>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
const QString AutoUpdater::platform = "win32";
|
||||
const QString AutoUpdater::updaterBin = "qtox-updater.exe";
|
||||
#else
|
||||
const QString AutoUpdater::platform;
|
||||
const QString AutoUpdater::updaterBin;
|
||||
#endif
|
||||
const QString AutoUpdater::updateServer = "http://mlkj.bounceme.net";
|
||||
const QString AutoUpdater::checkURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/version";
|
||||
const QString AutoUpdater::flistURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/flist";
|
||||
const QString AutoUpdater::filesURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/files/";
|
||||
unsigned char AutoUpdater::key[crypto_sign_PUBLICKEYBYTES] =
|
||||
{
|
||||
0xa5, 0x80, 0xf3, 0xb7, 0xd0, 0x10, 0xc0, 0xf9, 0xd6, 0xcf, 0x48, 0x15, 0x99, 0x70, 0x92, 0x49,
|
||||
0xf6, 0xe8, 0xe5, 0xe2, 0x6c, 0x73, 0x8c, 0x48, 0x25, 0xed, 0x01, 0x72, 0xf7, 0x6c, 0x17, 0x28
|
||||
};
|
||||
|
||||
bool AutoUpdater::isUpdateAvailable()
|
||||
{
|
||||
QString newVersion = getUpdateVersion();
|
||||
if (newVersion.isEmpty() || newVersion == GIT_VERSION)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
QString AutoUpdater::getUpdateVersion()
|
||||
{
|
||||
QString version;
|
||||
|
||||
// Updates only for supported platforms
|
||||
if (platform.isEmpty())
|
||||
return version;
|
||||
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager;
|
||||
QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(checkURI)));
|
||||
while (!reply->isFinished())
|
||||
qApp->processEvents();
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
qWarning() << "AutoUpdater: getUpdateVersion: network error: "<<reply->errorString();
|
||||
reply->deleteLater();
|
||||
manager->deleteLater();
|
||||
return version;
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
reply->deleteLater();
|
||||
manager->deleteLater();
|
||||
if (data.size() < (int)(1+crypto_sign_BYTES))
|
||||
return version;
|
||||
|
||||
// Check updater protocol version
|
||||
if ((int)data[0] != '1')
|
||||
{
|
||||
qWarning() << "AutoUpdater: getUpdateVersion: Bad version "<<(uint8_t)data[0];
|
||||
return version;
|
||||
}
|
||||
|
||||
// Check the signature
|
||||
QByteArray sigData = data.mid(1, crypto_sign_BYTES);
|
||||
unsigned char* sig = (unsigned char*)sigData.data();
|
||||
QByteArray msgData = data.mid(1+crypto_sign_BYTES);
|
||||
unsigned char* msg = (unsigned char*)msgData.data();
|
||||
|
||||
if (crypto_sign_verify_detached(sig, msg, msgData.size(), key) != 0)
|
||||
{
|
||||
qCritical() << "AutoUpdater: getUpdateVersion: RECEIVED FORGED VERSION FILE FROM "<<updateServer;
|
||||
return version;
|
||||
}
|
||||
|
||||
version = msgData;
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
QList<AutoUpdater::UpdateFileMeta> AutoUpdater::parseFlist(QByteArray flistData)
|
||||
{
|
||||
QList<UpdateFileMeta> 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;
|
||||
}
|
||||
|
||||
QByteArray AutoUpdater::getUpdateFlist()
|
||||
{
|
||||
QByteArray flist;
|
||||
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager;
|
||||
QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(flistURI)));
|
||||
while (!reply->isFinished())
|
||||
qApp->processEvents();
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
qWarning() << "AutoUpdater: getUpdateFlist: network error: "<<reply->errorString();
|
||||
reply->deleteLater();
|
||||
manager->deleteLater();
|
||||
return flist;
|
||||
}
|
||||
|
||||
flist = reply->readAll();
|
||||
reply->deleteLater();
|
||||
manager->deleteLater();
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
QByteArray AutoUpdater::getLocalFlist()
|
||||
{
|
||||
QByteArray flist;
|
||||
|
||||
QFile flistFile("flist");
|
||||
if (!flistFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qWarning() << "AutoUpdater::getLocalFlist: Can't open local flist";
|
||||
return flist;
|
||||
}
|
||||
|
||||
flist = flistFile.readAll();
|
||||
flistFile.close();
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
QList<AutoUpdater::UpdateFileMeta> AutoUpdater::genUpdateDiff(QList<UpdateFileMeta> updateFlist)
|
||||
{
|
||||
QList<UpdateFileMeta> diff;
|
||||
QList<UpdateFileMeta> localFlist = parseFlist(getLocalFlist());
|
||||
|
||||
for (UpdateFileMeta file : updateFlist)
|
||||
if (!localFlist.contains(file))
|
||||
diff += file;
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
AutoUpdater::UpdateFile AutoUpdater::getUpdateFile(UpdateFileMeta fileMeta)
|
||||
{
|
||||
UpdateFile file;
|
||||
file.metadata = fileMeta;
|
||||
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager;
|
||||
QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(filesURI+fileMeta.id)));
|
||||
while (!reply->isFinished())
|
||||
qApp->processEvents();
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
qWarning() << "AutoUpdater: getUpdateFile: network error: "<<reply->errorString();
|
||||
reply->deleteLater();
|
||||
manager->deleteLater();
|
||||
return file;
|
||||
}
|
||||
|
||||
file.data = reply->readAll();
|
||||
reply->deleteLater();
|
||||
manager->deleteLater();
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
bool AutoUpdater::downloadUpdate()
|
||||
{
|
||||
// Updates only for supported platforms
|
||||
if (platform.isEmpty())
|
||||
return false;
|
||||
|
||||
// Get a list of files to update
|
||||
QByteArray newFlistData = getUpdateFlist();
|
||||
QList<UpdateFileMeta> newFlist = parseFlist(newFlistData);
|
||||
QList<UpdateFileMeta> diff = genUpdateDiff(newFlist);
|
||||
|
||||
qDebug() << "AutoUpdater: Need to update "<<diff.size()<<" files";
|
||||
|
||||
// Create an empty directory to download updates into
|
||||
QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
|
||||
QDir updateDir(updateDirStr);
|
||||
if (updateDir.exists())
|
||||
updateDir.removeRecursively();
|
||||
QDir().mkdir(updateDirStr);
|
||||
updateDir = QDir(updateDirStr);
|
||||
if (!updateDir.exists())
|
||||
{
|
||||
qWarning() << "AutoUpdater::downloadUpdate: Can't create update directory, aborting...";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the new flist for the updater
|
||||
QFile newFlistFile(updateDirStr+"flist");
|
||||
if (!newFlistFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
||||
{
|
||||
qWarning() << "AutoUpdater::downloadUpdate: Can't save new flist file, aborting...";
|
||||
return false;
|
||||
}
|
||||
newFlistFile.write(newFlistData);
|
||||
newFlistFile.close();
|
||||
|
||||
// Download and write each new file
|
||||
for (UpdateFileMeta fileMeta : diff)
|
||||
{
|
||||
qDebug() << "AutoUpdater: Downloading '"+fileMeta.installpath+"' ...";
|
||||
|
||||
// Create subdirs if necessary
|
||||
QString fileDirStr{QFileInfo(updateDirStr+fileMeta.installpath).absolutePath()};
|
||||
if (!QDir(fileDirStr).exists())
|
||||
QDir().mkpath(fileDirStr);
|
||||
|
||||
// Download
|
||||
UpdateFile file = getUpdateFile(fileMeta);
|
||||
if (file.data.isNull())
|
||||
{
|
||||
qWarning() << "AutoUpdater::downloadUpdate: Error downloading a file, aborting...";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check signature
|
||||
if (crypto_sign_verify_detached(file.metadata.sig, (unsigned char*)file.data.data(),
|
||||
file.data.size(), key) != 0)
|
||||
{
|
||||
qCritical() << "AutoUpdater: downloadUpdate: RECEIVED FORGED FILE, aborting...";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save
|
||||
QFile fileFile(updateDirStr+fileMeta.installpath);
|
||||
if (!fileFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
||||
{
|
||||
qWarning() << "AutoUpdater::downloadUpdate: Can't save new update file, aborting...";
|
||||
return false;
|
||||
}
|
||||
fileFile.write(file.data);
|
||||
fileFile.close();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AutoUpdater::isLocalUpdateReady()
|
||||
{
|
||||
// Updates only for supported platforms
|
||||
if (platform.isEmpty())
|
||||
return false;
|
||||
|
||||
// Check that there's an update dir in the first place, valid or not
|
||||
QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
|
||||
QDir updateDir(updateDirStr);
|
||||
if (!updateDir.exists())
|
||||
return false;
|
||||
|
||||
// Check that we have a flist and that every file on the diff exists
|
||||
QFile updateFlistFile(updateDirStr+"flist");
|
||||
if (!updateFlistFile.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
QByteArray updateFlistData = updateFlistFile.readAll();
|
||||
updateFlistFile.close();
|
||||
|
||||
QList<UpdateFileMeta> updateFlist = parseFlist(updateFlistData);
|
||||
QList<UpdateFileMeta> diff = genUpdateDiff(updateFlist);
|
||||
|
||||
for (UpdateFileMeta fileMeta : diff)
|
||||
if (!QFile::exists(updateDirStr+fileMeta.installpath))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AutoUpdater::installLocalUpdate()
|
||||
{
|
||||
qDebug() << "AutoUpdater: About to start the qTox updater to install a local update";
|
||||
|
||||
// Delete the update if we fail so we don't fail again.
|
||||
|
||||
// Updates only for supported platforms.
|
||||
if (platform.isEmpty())
|
||||
{
|
||||
qCritical() << "AutoUpdater: Failed to start the qTox updater, removing the update and exiting";
|
||||
QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
|
||||
QDir(updateDirStr).removeRecursively();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Workaround QTBUG-7645
|
||||
// QProcess fails silently when elevation is required instead of showing a UAC prompt on Win7/Vista
|
||||
#ifdef Q_OS_WIN
|
||||
int result = (int)::ShellExecuteA(0, "open", updaterBin.toUtf8().constData(), 0, 0, SW_SHOWNORMAL);
|
||||
if (SE_ERR_ACCESSDENIED == result)
|
||||
{
|
||||
// Requesting elevation
|
||||
result = (int)::ShellExecuteA(0, "runas", updaterBin.toUtf8().constData(), 0, 0, SW_SHOWNORMAL);
|
||||
}
|
||||
if (result <= 32)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
if (!QProcess::startDetached(updaterBin))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
exit(0);
|
||||
|
||||
// Centralized error handling
|
||||
fail:
|
||||
qCritical() << "AutoUpdater: Failed to start the qTox updater, removing the update and exiting";
|
||||
QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
|
||||
QDir(updateDirStr).removeRecursively();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void AutoUpdater::checkUpdatesAsyncInteractive()
|
||||
{
|
||||
QtConcurrent::run(&AutoUpdater::checkUpdatesAsyncInteractiveWorker);
|
||||
}
|
||||
|
||||
void AutoUpdater::checkUpdatesAsyncInteractiveWorker()
|
||||
{
|
||||
if (!isUpdateAvailable())
|
||||
return;
|
||||
|
||||
if (Widget::getInstance()->askMsgboxQuestion(QObject::tr("Update", "The title of a message box"),
|
||||
QObject::tr("An update is available, do you want to download it now ?\nIt will be installed when qTox restarts.")))
|
||||
{
|
||||
downloadUpdate();
|
||||
}
|
||||
}
|
115
src/autoupdate.h
Normal file
115
src/autoupdate.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AUTOUPDATE_H
|
||||
#define AUTOUPDATE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <sodium.h>
|
||||
|
||||
/// For now we only support auto updates on Windows, although extending it is not a technical issue.
|
||||
/// Linux and Mac users are expected to use their package managers or update manually through official channels.
|
||||
#ifdef Q_OS_WIN
|
||||
#define AUTOUPDATE_ENABLED 1
|
||||
#else
|
||||
#define AUTOUPDATE_ENABLED 0
|
||||
#endif
|
||||
|
||||
/// Handles checking and applying updates for qTox
|
||||
/// Do *NOT* use auto update unless AUTOUPDATE_ENABLED is defined to 1
|
||||
class AutoUpdater
|
||||
{
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
public:
|
||||
/// Connects to the qTox update server, if an updat is found shows a dialog to the user asking to download it
|
||||
/// Runs asynchronously in its own thread, and will return immediatly
|
||||
/// Will call isUpdateAvailable, and as such may processEvents
|
||||
static void checkUpdatesAsyncInteractive();
|
||||
/// Connects to the qTox update server, returns true if an update is available for download
|
||||
/// Will call getUpdateVersion, and as such may block and processEvents
|
||||
static bool isUpdateAvailable();
|
||||
/// Fetch the version string of the last update available from the qTox update server
|
||||
/// Will try to follow qTox's proxy settings, may block and processEvents
|
||||
static QString getUpdateVersion();
|
||||
/// Will try to download an update, if successful returns true and qTox will apply it after a restart
|
||||
/// Will try to follow qTox's proxy settings, may block and processEvents
|
||||
static bool downloadUpdate();
|
||||
/// Returns true if an update is downloaded and ready to be installed
|
||||
/// If so, call installLocalUpdate. If not, call downloadUpdate.
|
||||
/// This only checks that we downloaded an update and didn't stop in the middle, not that every file is still valid
|
||||
static bool isLocalUpdateReady();
|
||||
/// Launches the qTox updater to try to install the local update and exits immediately
|
||||
/// Will not check that the update actually exists, use isLocalUpdateReady first for that
|
||||
/// The qTox updater will restart us after the update is done
|
||||
/// Note: If we fail to start the qTox updater, we will delete the update and exit
|
||||
[[ noreturn ]] static void installLocalUpdate();
|
||||
|
||||
protected:
|
||||
/// Parses and validates a flist file. Returns an empty list on error
|
||||
static QList<UpdateFileMeta> parseFlist(QByteArray flistData);
|
||||
/// Gets the update server's flist. Returns an empty array on error
|
||||
/// Will try to follow qTox's proxy settings, may block and processEvents
|
||||
static QByteArray getUpdateFlist();
|
||||
/// Gets the local flist. Returns an empty array on error
|
||||
static QByteArray getLocalFlist();
|
||||
/// Generates a list of files we need to update
|
||||
static QList<UpdateFileMeta> genUpdateDiff(QList<UpdateFileMeta> updateFlist);
|
||||
/// Tries to fetch the file from the update server. Returns a file with a null QByteArray on error.
|
||||
/// Note that a file with an empty but non-null QByteArray is not an error, merely a file of size 0.
|
||||
/// Will try to follow qTox's proxy settings, may block and processEvents
|
||||
static UpdateFile getUpdateFile(UpdateFileMeta fileMeta);
|
||||
/// Does the actual work for checkUpdatesAsyncInteractive
|
||||
/// Blocking, but otherwise has the same properties than checkUpdatesAsyncInteractive
|
||||
static void checkUpdatesAsyncInteractiveWorker();
|
||||
|
||||
private:
|
||||
AutoUpdater() = delete;
|
||||
|
||||
private:
|
||||
// Constants
|
||||
static const QString updateServer; ///< Hostname of the qTox update server
|
||||
static const QString platform; ///< Name of platform we're trying to get updates for
|
||||
static const QString checkURI; ///< URI of the file containing the latest version string
|
||||
static const QString flistURI; ///< URI of the file containing info on each file (hash, signature, size, name, ..)
|
||||
static const QString filesURI; ///< URI of the actual files of the latest version
|
||||
static const QString updaterBin; ///< Path to the qtox-updater binary
|
||||
static unsigned char key[];
|
||||
};
|
||||
|
||||
#endif // AUTOUPDATE_H
|
13
src/main.cpp
13
src/main.cpp
|
@ -19,6 +19,7 @@
|
|||
#include "src/ipc.h"
|
||||
#include "src/widget/toxuri.h"
|
||||
#include "src/widget/toxsave.h"
|
||||
#include "src/autoupdate.h"
|
||||
#include <QApplication>
|
||||
#include <QFontDatabase>
|
||||
#include <QDebug>
|
||||
|
@ -27,6 +28,8 @@
|
|||
#include <QDateTime>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
#ifdef LOG_TO_FILE
|
||||
static QtMessageHandler dflt;
|
||||
static QTextStream* logFile {nullptr};
|
||||
|
@ -55,6 +58,8 @@ int main(int argc, char *argv[])
|
|||
a.setApplicationName("qTox");
|
||||
a.setOrganizationName("Tox");
|
||||
|
||||
sodium_init(); // For the auto-updater
|
||||
|
||||
#ifdef LOG_TO_FILE
|
||||
logFile = new QTextStream;
|
||||
dflt = qInstallMessageHandler(nullptr);
|
||||
|
@ -83,6 +88,12 @@ int main(int argc, char *argv[])
|
|||
// Install Unicode 6.1 supporting font
|
||||
QFontDatabase::addApplicationFont("://DejaVuSans.ttf");
|
||||
|
||||
// Check whether we have an update waiting to be installed
|
||||
#if AUTOUPDATE_ENABLED
|
||||
if (AutoUpdater::isLocalUpdateReady())
|
||||
AutoUpdater::installLocalUpdate(); ///< NORETURN
|
||||
#endif
|
||||
|
||||
// Inter-process communication
|
||||
IPC ipc;
|
||||
ipc.registerEventHandler(&toxURIEventHandler);
|
||||
|
@ -127,7 +138,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
// Run
|
||||
Widget* w = Widget::getInstance();
|
||||
Widget* w = Widget::getInstance();
|
||||
int errorcode = a.exec();
|
||||
|
||||
delete w;
|
||||
|
|
254
src/misc/serialize.cpp
Normal file
254
src/misc/serialize.cpp
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "src/misc/serialize.h"
|
||||
|
||||
QByteArray doubleToData(double num)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[8];
|
||||
double n;
|
||||
} castUnion;
|
||||
//char n[8];
|
||||
//*((double*) n) = num;
|
||||
|
||||
castUnion.n=num;
|
||||
return QByteArray(castUnion.tab,8);
|
||||
}
|
||||
|
||||
QByteArray floatToData(float num)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[4];
|
||||
float n;
|
||||
} castUnion;
|
||||
|
||||
castUnion.n=num;
|
||||
return QByteArray(castUnion.tab,4);
|
||||
}
|
||||
|
||||
float dataToFloat(QByteArray data)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[4];
|
||||
float n;
|
||||
} castUnion;
|
||||
|
||||
castUnion.tab[0]=data.data()[0];
|
||||
castUnion.tab[1]=data.data()[1];
|
||||
castUnion.tab[2]=data.data()[2];
|
||||
castUnion.tab[3]=data.data()[3];
|
||||
return castUnion.n;
|
||||
}
|
||||
|
||||
// Converts a string into PNet string data
|
||||
QByteArray stringToData(QString str)
|
||||
{
|
||||
QByteArray data(4,0);
|
||||
// Write the size in a Uint of variable lenght (8-32 bits)
|
||||
int i=0;
|
||||
uint num1 = (uint)str.toUtf8().size();
|
||||
while (num1 >= 0x80)
|
||||
{
|
||||
data[i] = (unsigned char)(num1 | 0x80); i++;
|
||||
num1 = num1 >> 7;
|
||||
}
|
||||
data[i]=num1;
|
||||
data.resize(i+1);
|
||||
data+=str.toUtf8();
|
||||
return data;
|
||||
}
|
||||
|
||||
QString dataToString(QByteArray data)
|
||||
{
|
||||
// Variable UInt32
|
||||
unsigned char num3;
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
int i=0;
|
||||
do
|
||||
{
|
||||
num3 = data[i]; i++;
|
||||
num |= (num3 & 0x7f) << num2;
|
||||
num2 += 7;
|
||||
} while ((num3 & 0x80) != 0);
|
||||
unsigned int strlen = (uint) num;
|
||||
|
||||
if (!strlen)
|
||||
return QString();
|
||||
|
||||
data = data.right(data.size()-i); // Remove the strlen
|
||||
data.truncate(strlen);
|
||||
return QString(data);
|
||||
}
|
||||
|
||||
float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data)
|
||||
{
|
||||
uint endvalue=0;
|
||||
uint value=0;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
endvalue = (uchar)data[0];
|
||||
goto done;
|
||||
}
|
||||
value = (uchar)data[0];
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
endvalue = (value | ((uint) ((uchar)data[1]) << 8));
|
||||
goto done;
|
||||
}
|
||||
value |= (uint) (((uchar)data[1]) << 8);
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
uint num2 = (uint) (((uchar)data[2]) << 0x10);
|
||||
endvalue = (value | num2);
|
||||
goto done;
|
||||
}
|
||||
value |= (uint) (((uchar)data[2]) << 0x10);
|
||||
numberOfBits -= 8;
|
||||
endvalue = (value | ((uint) (((uchar)data[3]) << 0x18)));
|
||||
goto done;
|
||||
|
||||
done:
|
||||
|
||||
float num = max - min;
|
||||
int num2 = (((int) 1) << numberOfBits) - 1;
|
||||
float num3 = endvalue;
|
||||
float num4 = num3 / ((float) num2);
|
||||
return (min + (num4 * num));
|
||||
}
|
||||
|
||||
QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits)
|
||||
{
|
||||
QByteArray data;
|
||||
float num = max - min;
|
||||
float num2 = (value - min) / num;
|
||||
int num3 = (((int) 1) << numberOfBits) - 1;
|
||||
uint source = num3 * num2;
|
||||
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source;
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source>>8;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source>>8;
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source>>16;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source>>16;
|
||||
data += (unsigned char)source>>24;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t dataToUint8(QByteArray data)
|
||||
{
|
||||
return (uint8_t)data[0];
|
||||
}
|
||||
|
||||
uint16_t dataToUint16(QByteArray data)
|
||||
{
|
||||
return ((uint16_t)(uint8_t)data[0])
|
||||
+(((uint16_t)(uint8_t)data[1])<<8);
|
||||
}
|
||||
|
||||
uint32_t dataToUint32(QByteArray data)
|
||||
{
|
||||
return ((uint32_t)(uint8_t)data[0])
|
||||
+(((uint32_t)(uint8_t)data[1])<<8)
|
||||
+(((uint32_t)(uint8_t)data[2])<<16)
|
||||
+(((uint32_t)(uint8_t)data[3])<<24);
|
||||
}
|
||||
|
||||
uint64_t dataToUint64(QByteArray data)
|
||||
{
|
||||
return ((uint64_t)(uint8_t)data[0])
|
||||
+(((uint64_t)(uint8_t)data[1])<<8)
|
||||
+(((uint64_t)(uint8_t)data[2])<<16)
|
||||
+(((uint64_t)(uint8_t)data[3])<<24)
|
||||
+(((uint64_t)(uint8_t)data[4])<<32)
|
||||
+(((uint64_t)(uint8_t)data[5])<<40)
|
||||
+(((uint64_t)(uint8_t)data[6])<<48)
|
||||
+(((uint64_t)(uint8_t)data[7])<<56);
|
||||
}
|
||||
|
||||
unsigned getVUint32Size(QByteArray data)
|
||||
{
|
||||
unsigned lensize=0;
|
||||
{
|
||||
unsigned char num3;
|
||||
do {
|
||||
num3 = data[lensize];
|
||||
lensize++;
|
||||
} while ((num3 & 0x80) != 0);
|
||||
}
|
||||
return lensize;
|
||||
}
|
||||
|
||||
QByteArray uint8ToData(uint8_t num)
|
||||
{
|
||||
QByteArray data(1,0);
|
||||
data[0] = (uint8_t)num;
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint16ToData(uint16_t num)
|
||||
{
|
||||
QByteArray data(2,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint32ToData(uint32_t num)
|
||||
{
|
||||
QByteArray data(4,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
data[2] = (uint8_t)((num>>16) & 0xFF);
|
||||
data[3] = (uint8_t)((num>>24) & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint64ToData(uint64_t num)
|
||||
{
|
||||
QByteArray data(8,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
data[2] = (uint8_t)((num>>16) & 0xFF);
|
||||
data[3] = (uint8_t)((num>>24) & 0xFF);
|
||||
data[4] = (uint8_t)((num>>32) & 0xFF);
|
||||
data[5] = (uint8_t)((num>>40) & 0xFF);
|
||||
data[6] = (uint8_t)((num>>48) & 0xFF);
|
||||
data[7] = (uint8_t)((num>>56) & 0xFF);
|
||||
return data;
|
||||
}
|
45
src/misc/serialize.h
Normal file
45
src/misc/serialize.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SERIALIZE_H
|
||||
#define SERIALIZE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
/// Most of those functions are unsafe unless otherwise specified
|
||||
/// Do not use them on untrusted data (e.g. check a signature first)
|
||||
|
||||
QByteArray doubleToData(double num);
|
||||
QByteArray floatToData(float num);
|
||||
float dataToFloat(QByteArray data);
|
||||
QByteArray stringToData(QString str);
|
||||
QString dataToString(QByteArray data);
|
||||
float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data);
|
||||
QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits);
|
||||
uint8_t dataToUint8(QByteArray data);
|
||||
uint16_t dataToUint16(QByteArray data);
|
||||
uint32_t dataToUint32(QByteArray data);
|
||||
uint64_t dataToUint64(QByteArray data);
|
||||
unsigned getVUint32Size(QByteArray data);
|
||||
QByteArray uint8ToData(uint8_t num);
|
||||
QByteArray uint16ToData(uint16_t num);
|
||||
QByteArray uint32ToData(uint32_t num);
|
||||
QByteArray uint64ToData(uint64_t num);
|
||||
|
||||
#endif // SERIALIZE_H
|
|
@ -119,6 +119,7 @@ void Settings::load()
|
|||
proxyPort = s.value("proxyPort", 0).toInt();
|
||||
currentProfile = s.value("currentProfile", "").toString();
|
||||
autoAwayTime = s.value("autoAwayTime", 10).toInt();
|
||||
checkUpdates = s.value("checkUpdates", false).toBool();
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup("Widgets");
|
||||
|
@ -255,6 +256,7 @@ void Settings::save(QString path)
|
|||
s.setValue("proxyPort", proxyPort);
|
||||
s.setValue("currentProfile", currentProfile);
|
||||
s.setValue("autoAwayTime", autoAwayTime);
|
||||
s.setValue("checkUpdates", checkUpdates);
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup("Widgets");
|
||||
|
@ -727,6 +729,16 @@ void Settings::setWindowState(const QByteArray &value)
|
|||
windowState = value;
|
||||
}
|
||||
|
||||
bool Settings::getCheckUpdates() const
|
||||
{
|
||||
return checkUpdates;
|
||||
}
|
||||
|
||||
void Settings::setCheckUpdates(bool newValue)
|
||||
{
|
||||
checkUpdates = newValue;
|
||||
}
|
||||
|
||||
QByteArray Settings::getSplitterState() const
|
||||
{
|
||||
return splitterState;
|
||||
|
|
|
@ -99,6 +99,9 @@ public:
|
|||
int getAutoAwayTime() const;
|
||||
void setAutoAwayTime(int newValue);
|
||||
|
||||
bool getCheckUpdates() const;
|
||||
void setCheckUpdates(bool newValue);
|
||||
|
||||
QPixmap getSavedAvatar(const QString& ownerId);
|
||||
void saveAvatar(QPixmap& pic, const QString& ownerId);
|
||||
|
||||
|
@ -219,6 +222,7 @@ private:
|
|||
bool closeToTray;
|
||||
bool minimizeToTray;
|
||||
bool useEmoticons;
|
||||
bool checkUpdates;
|
||||
|
||||
bool forceTCP;
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <QFileDialog>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "src/autoupdate.h"
|
||||
|
||||
static QStringList locales = {"bg", "de", "en", "fr", "it", "mannol", "pirate", "pl", "ru", "fi", "sv", "uk"};
|
||||
static QStringList langs = {"Български", "Deustch", "English", "Français", "Italiano", "mannol", "Pirate", "Polski", "Русский", "Suomi", "Svenska", "Українська"};
|
||||
|
||||
|
@ -39,6 +41,9 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
|
|||
|
||||
bodyUI = new Ui::GeneralSettings;
|
||||
bodyUI->setupUi(this);
|
||||
|
||||
bodyUI->checkUpdates->setVisible(AUTOUPDATE_ENABLED);
|
||||
bodyUI->checkUpdates->setChecked(Settings::getInstance().getCheckUpdates());
|
||||
|
||||
bodyUI->cbEnableIPv6->setChecked(Settings::getInstance().getEnableIPv6());
|
||||
for (int i = 0; i < langs.size(); i++)
|
||||
|
@ -93,6 +98,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
|
|||
onUseProxyUpdated();
|
||||
|
||||
//general
|
||||
connect(bodyUI->checkUpdates, &QCheckBox::stateChanged, this, &GeneralForm::onCheckUpdateChanged);
|
||||
connect(bodyUI->transComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onTranslationUpdated()));
|
||||
connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &GeneralForm::onMakeToxPortableUpdated);
|
||||
connect(bodyUI->startInTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetAutostartInTray);
|
||||
|
@ -280,3 +286,8 @@ void GeneralForm::reloadSmiles()
|
|||
bodyUI->smile4->setToolTip(smiles[3]);
|
||||
bodyUI->smile5->setToolTip(smiles[4]);
|
||||
}
|
||||
|
||||
void GeneralForm::onCheckUpdateChanged()
|
||||
{
|
||||
Settings::getInstance().setCheckUpdates(bodyUI->checkUpdates->isChecked());
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ private slots:
|
|||
void onReconnectClicked();
|
||||
void onAutoAcceptFileChange();
|
||||
void onAutoSaveDirChange();
|
||||
void onCheckUpdateChanged();
|
||||
|
||||
private:
|
||||
Ui::GeneralSettings *bodyUI;
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>511</width>
|
||||
<height>739</height>
|
||||
<height>720</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,1">
|
||||
|
@ -121,6 +121,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkUpdates">
|
||||
<property name="text">
|
||||
<string>Check for updates on startup (unstable)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item alignment="Qt::AlignLeft">
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#include "src/video/camera.h"
|
||||
#include "form/chatform.h"
|
||||
#include "maskablepixmapwidget.h"
|
||||
#include "src/historykeeper.h"
|
||||
#include "form/inputpassworddialog.h"
|
||||
#include "src/autoupdate.h"
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
@ -45,9 +48,7 @@
|
|||
#include <QTimer>
|
||||
#include <QStyleFactory>
|
||||
#include <QTranslator>
|
||||
#include "src/historykeeper.h"
|
||||
#include <tox/tox.h>
|
||||
#include "form/inputpassworddialog.h"
|
||||
|
||||
Widget *Widget::instance{nullptr};
|
||||
|
||||
|
@ -244,6 +245,11 @@ void Widget::init()
|
|||
coreThread->start();
|
||||
|
||||
addFriendForm->show(*ui);
|
||||
|
||||
#if (AUTOUPDATE_ENABLED)
|
||||
if (Settings::getInstance().getCheckUpdates())
|
||||
AutoUpdater::checkUpdatesAsyncInteractive();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Widget::setTranslation()
|
||||
|
@ -1095,3 +1101,20 @@ void Widget::setEnabledThreadsafe(bool enabled)
|
|||
return setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::askMsgboxQuestion(const QString& title, const QString& msg)
|
||||
{
|
||||
// We can only display widgets from the GUI thread
|
||||
if (QThread::currentThread() != qApp->thread())
|
||||
{
|
||||
bool ret;
|
||||
QMetaObject::invokeMethod(this, "askMsgboxQuestion", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ret),
|
||||
Q_ARG(const QString&, title), Q_ARG(const QString&, msg));
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QMessageBox::question(this, title, msg) == QMessageBox::StandardButton::Yes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
Q_INVOKABLE QMessageBox::StandardButton showWarningMsgBox(const QString& title, const QString& msg,
|
||||
QMessageBox::StandardButtons buttonss = QMessageBox::Ok);
|
||||
Q_INVOKABLE void setEnabledThreadsafe(bool enabled);
|
||||
Q_INVOKABLE bool askMsgboxQuestion(const QString& title, const QString& msg);
|
||||
~Widget();
|
||||
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
|
|
97
tools/update-server/qtox-updater-genflist/main.cpp
Normal file
97
tools/update-server/qtox-updater-genflist/main.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include <iostream>
|
||||
#include <QFile>
|
||||
#include <QByteArray>
|
||||
#include <QDir>
|
||||
#include <QCryptographicHash>
|
||||
#include <sodium.h>
|
||||
#include "serialize.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// Pass the target folder as first argument, no spaces allowed. We'll call that dir $TARGET
|
||||
/// Update the content of $TARGET/files/ before calling this tool
|
||||
/// We'll generate $TARGET/flist and exit
|
||||
/// We need qtox-updater-skey in our working directory to sign the flist
|
||||
///
|
||||
/// The generated flist is very simple and just installs everything in the working directory ...
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
cout << "qTox updater flist generator" << endl;
|
||||
|
||||
/// First some basic error handling, prepare our handles, ...
|
||||
if (argc != 2)
|
||||
{
|
||||
cout << "ERROR: qtox-updater-genflist takes the target path in argument" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
QFile skeyFile("qtox-updater-skey");
|
||||
if (!skeyFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
cout << "ERROR: qtox-updater-genflist can't open the secret (private) key file" << endl;
|
||||
return 1;
|
||||
}
|
||||
QByteArray skeyData = skeyFile.readAll();
|
||||
skeyData = QByteArray::fromHex(skeyData);
|
||||
skeyFile.close();
|
||||
|
||||
QString target(argv[1]);
|
||||
|
||||
QFile flistFile(target+"/flist");
|
||||
if (!flistFile.open(QIODevice::Truncate | QIODevice::WriteOnly))
|
||||
{
|
||||
cout << "ERROR: qtox-updater-genflist can't open the target flist" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
QDir fdir(target+"/files/");
|
||||
if (!fdir.isReadable())
|
||||
{
|
||||
cout << "ERROR: qtox-updater-genflist can't open the target files directory" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
QStringList filesListStr = fdir.entryList(QDir::Files);
|
||||
|
||||
/// Serialize the flist data
|
||||
QByteArray flistData;
|
||||
for (QString fileStr : filesListStr)
|
||||
{
|
||||
cout << "Adding "<<fileStr.toStdString()<<"..."<<endl;
|
||||
|
||||
QFile file(target+"/files/"+fileStr);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
cout << "ERROR: qtox-updater-genflist couldn't open a target file to sign it" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
QByteArray fileData = file.readAll();
|
||||
|
||||
unsigned char sig[crypto_sign_BYTES];
|
||||
crypto_sign_detached(sig, nullptr, (unsigned char*)fileData.data(), fileData.size(), (unsigned char*)skeyData.data());
|
||||
|
||||
flistData += QByteArray::fromRawData((char*)sig, crypto_sign_BYTES);
|
||||
flistData += stringToData(QCryptographicHash::hash(fileStr.toUtf8(), QCryptographicHash::Sha3_224).toHex());
|
||||
flistData += stringToData("./"+fileStr); ///< Always install in the working directory for now
|
||||
flistData += uint64ToData(fileData.size());
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
cout << "Signing and writing the flist..."<<endl;
|
||||
|
||||
/// Sign our flist
|
||||
unsigned char sig[crypto_sign_BYTES];
|
||||
crypto_sign_detached(sig, nullptr, (unsigned char*)flistData.data(), flistData.size(), (unsigned char*)skeyData.data());
|
||||
|
||||
/// Write the flist
|
||||
flistFile.write("1");
|
||||
flistFile.write((char*)sig, crypto_sign_BYTES);
|
||||
flistFile.write(flistData);
|
||||
|
||||
flistFile.close();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
TEMPLATE = app
|
||||
CONFIG += console c++11
|
||||
QT += core
|
||||
LIBS += -lsodium
|
||||
|
||||
SOURCES += main.cpp \
|
||||
serialize.cpp
|
||||
|
||||
HEADERS += \
|
||||
serialize.h
|
254
tools/update-server/qtox-updater-genflist/serialize.cpp
Normal file
254
tools/update-server/qtox-updater-genflist/serialize.cpp
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
QByteArray doubleToData(double num)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[8];
|
||||
double n;
|
||||
} castUnion;
|
||||
//char n[8];
|
||||
//*((double*) n) = num;
|
||||
|
||||
castUnion.n=num;
|
||||
return QByteArray(castUnion.tab,8);
|
||||
}
|
||||
|
||||
QByteArray floatToData(float num)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[4];
|
||||
float n;
|
||||
} castUnion;
|
||||
|
||||
castUnion.n=num;
|
||||
return QByteArray(castUnion.tab,4);
|
||||
}
|
||||
|
||||
float dataToFloat(QByteArray data)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[4];
|
||||
float n;
|
||||
} castUnion;
|
||||
|
||||
castUnion.tab[0]=data.data()[0];
|
||||
castUnion.tab[1]=data.data()[1];
|
||||
castUnion.tab[2]=data.data()[2];
|
||||
castUnion.tab[3]=data.data()[3];
|
||||
return castUnion.n;
|
||||
}
|
||||
|
||||
// Converts a string into PNet string data
|
||||
QByteArray stringToData(QString str)
|
||||
{
|
||||
QByteArray data(4,0);
|
||||
// Write the size in a Uint of variable lenght (8-32 bits)
|
||||
int i=0;
|
||||
uint num1 = (uint)str.toUtf8().size();
|
||||
while (num1 >= 0x80)
|
||||
{
|
||||
data[i] = (unsigned char)(num1 | 0x80); i++;
|
||||
num1 = num1 >> 7;
|
||||
}
|
||||
data[i]=num1;
|
||||
data.resize(i+1);
|
||||
data+=str.toUtf8();
|
||||
return data;
|
||||
}
|
||||
|
||||
QString dataToString(QByteArray data)
|
||||
{
|
||||
// Variable UInt32
|
||||
unsigned char num3;
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
int i=0;
|
||||
do
|
||||
{
|
||||
num3 = data[i]; i++;
|
||||
num |= (num3 & 0x7f) << num2;
|
||||
num2 += 7;
|
||||
} while ((num3 & 0x80) != 0);
|
||||
unsigned int strlen = (uint) num;
|
||||
|
||||
if (!strlen)
|
||||
return QString();
|
||||
|
||||
data = data.right(data.size()-i); // Remove the strlen
|
||||
data.truncate(strlen);
|
||||
return QString(data);
|
||||
}
|
||||
|
||||
float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data)
|
||||
{
|
||||
uint endvalue=0;
|
||||
uint value=0;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
endvalue = (uchar)data[0];
|
||||
goto done;
|
||||
}
|
||||
value = (uchar)data[0];
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
endvalue = (value | ((uint) ((uchar)data[1]) << 8));
|
||||
goto done;
|
||||
}
|
||||
value |= (uint) (((uchar)data[1]) << 8);
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
uint num2 = (uint) (((uchar)data[2]) << 0x10);
|
||||
endvalue = (value | num2);
|
||||
goto done;
|
||||
}
|
||||
value |= (uint) (((uchar)data[2]) << 0x10);
|
||||
numberOfBits -= 8;
|
||||
endvalue = (value | ((uint) (((uchar)data[3]) << 0x18)));
|
||||
goto done;
|
||||
|
||||
done:
|
||||
|
||||
float num = max - min;
|
||||
int num2 = (((int) 1) << numberOfBits) - 1;
|
||||
float num3 = endvalue;
|
||||
float num4 = num3 / ((float) num2);
|
||||
return (min + (num4 * num));
|
||||
}
|
||||
|
||||
QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits)
|
||||
{
|
||||
QByteArray data;
|
||||
float num = max - min;
|
||||
float num2 = (value - min) / num;
|
||||
int num3 = (((int) 1) << numberOfBits) - 1;
|
||||
uint source = num3 * num2;
|
||||
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source;
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source>>8;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source>>8;
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source>>16;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source>>16;
|
||||
data += (unsigned char)source>>24;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t dataToUint8(QByteArray data)
|
||||
{
|
||||
return (uint8_t)data[0];
|
||||
}
|
||||
|
||||
uint16_t dataToUint16(QByteArray data)
|
||||
{
|
||||
return ((uint16_t)(uint8_t)data[0])
|
||||
+(((uint16_t)(uint8_t)data[1])<<8);
|
||||
}
|
||||
|
||||
uint32_t dataToUint32(QByteArray data)
|
||||
{
|
||||
return ((uint32_t)(uint8_t)data[0])
|
||||
+(((uint32_t)(uint8_t)data[1])<<8)
|
||||
+(((uint32_t)(uint8_t)data[2])<<16)
|
||||
+(((uint32_t)(uint8_t)data[3])<<24);
|
||||
}
|
||||
|
||||
uint64_t dataToUint64(QByteArray data)
|
||||
{
|
||||
return ((uint64_t)(uint8_t)data[0])
|
||||
+(((uint64_t)(uint8_t)data[1])<<8)
|
||||
+(((uint64_t)(uint8_t)data[2])<<16)
|
||||
+(((uint64_t)(uint8_t)data[3])<<24)
|
||||
+(((uint64_t)(uint8_t)data[4])<<32)
|
||||
+(((uint64_t)(uint8_t)data[5])<<40)
|
||||
+(((uint64_t)(uint8_t)data[6])<<48)
|
||||
+(((uint64_t)(uint8_t)data[7])<<56);
|
||||
}
|
||||
|
||||
unsigned getVUint32Size(QByteArray data)
|
||||
{
|
||||
unsigned lensize=0;
|
||||
{
|
||||
unsigned char num3;
|
||||
do {
|
||||
num3 = data[lensize];
|
||||
lensize++;
|
||||
} while ((num3 & 0x80) != 0);
|
||||
}
|
||||
return lensize;
|
||||
}
|
||||
|
||||
QByteArray uint8ToData(uint8_t num)
|
||||
{
|
||||
QByteArray data(1,0);
|
||||
data[0] = (uint8_t)num;
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint16ToData(uint16_t num)
|
||||
{
|
||||
QByteArray data(2,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint32ToData(uint32_t num)
|
||||
{
|
||||
QByteArray data(4,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
data[2] = (uint8_t)((num>>16) & 0xFF);
|
||||
data[3] = (uint8_t)((num>>24) & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint64ToData(uint64_t num)
|
||||
{
|
||||
QByteArray data(8,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
data[2] = (uint8_t)((num>>16) & 0xFF);
|
||||
data[3] = (uint8_t)((num>>24) & 0xFF);
|
||||
data[4] = (uint8_t)((num>>32) & 0xFF);
|
||||
data[5] = (uint8_t)((num>>40) & 0xFF);
|
||||
data[6] = (uint8_t)((num>>48) & 0xFF);
|
||||
data[7] = (uint8_t)((num>>56) & 0xFF);
|
||||
return data;
|
||||
}
|
45
tools/update-server/qtox-updater-genflist/serialize.h
Normal file
45
tools/update-server/qtox-updater-genflist/serialize.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SERIALIZE_H
|
||||
#define SERIALIZE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
/// Most of those functions are unsafe unless otherwise specified
|
||||
/// Do not use them on untrusted data (e.g. check a signature first)
|
||||
|
||||
QByteArray doubleToData(double num);
|
||||
QByteArray floatToData(float num);
|
||||
float dataToFloat(QByteArray data);
|
||||
QByteArray stringToData(QString str);
|
||||
QString dataToString(QByteArray data);
|
||||
float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data);
|
||||
QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits);
|
||||
uint8_t dataToUint8(QByteArray data);
|
||||
uint16_t dataToUint16(QByteArray data);
|
||||
uint32_t dataToUint32(QByteArray data);
|
||||
uint64_t dataToUint64(QByteArray data);
|
||||
unsigned getVUint32Size(QByteArray data);
|
||||
QByteArray uint8ToData(uint8_t num);
|
||||
QByteArray uint16ToData(uint16_t num);
|
||||
QByteArray uint32ToData(uint32_t num);
|
||||
QByteArray uint64ToData(uint64_t num);
|
||||
|
||||
#endif // SERIALIZE_H
|
43
tools/update-server/qtox-updater-sign/main.cpp
Normal file
43
tools/update-server/qtox-updater-sign/main.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include <sodium.h>
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QFile io;
|
||||
QByteArray msg;
|
||||
if (argc > 1)
|
||||
{
|
||||
msg = QByteArray(argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
io.open(stdin, QIODevice::ReadOnly);
|
||||
msg = io.readAll();
|
||||
io.close();
|
||||
}
|
||||
io.open(stdout, QIODevice::WriteOnly);
|
||||
|
||||
QFile skeyFile("qtox-updater-skey");
|
||||
if (!skeyFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
io.write("ERROR: qtox-updater-sign can't open the secret (private) key file\n");
|
||||
io.close();
|
||||
return 1;
|
||||
}
|
||||
QByteArray skeyData = skeyFile.readAll();
|
||||
skeyData = QByteArray::fromHex(skeyData);
|
||||
skeyFile.close();
|
||||
|
||||
unsigned char sig[crypto_sign_BYTES];
|
||||
crypto_sign_detached(sig, nullptr, (unsigned char*)msg.data(), msg.size(), (unsigned char*)skeyData.data());
|
||||
|
||||
io.write((char*)sig, crypto_sign_BYTES);
|
||||
io.write(msg);
|
||||
io.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
TEMPLATE = app
|
||||
CONFIG += console c++11
|
||||
QT += core
|
||||
|
||||
SOURCES += main.cpp
|
||||
|
||||
LIBS += -lsodium
|
28
updater/main.cpp
Normal file
28
updater/main.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "widget.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
Widget w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
5
updater/res.qrc
Normal file
5
updater/res.qrc
Normal file
|
@ -0,0 +1,5 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>res/qtox-256x256.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
BIN
updater/res/qtox-256x256.png
Normal file
BIN
updater/res/qtox-256x256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
254
updater/serialize.cpp
Normal file
254
updater/serialize.cpp
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
QByteArray doubleToData(double num)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[8];
|
||||
double n;
|
||||
} castUnion;
|
||||
//char n[8];
|
||||
//*((double*) n) = num;
|
||||
|
||||
castUnion.n=num;
|
||||
return QByteArray(castUnion.tab,8);
|
||||
}
|
||||
|
||||
QByteArray floatToData(float num)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[4];
|
||||
float n;
|
||||
} castUnion;
|
||||
|
||||
castUnion.n=num;
|
||||
return QByteArray(castUnion.tab,4);
|
||||
}
|
||||
|
||||
float dataToFloat(QByteArray data)
|
||||
{
|
||||
union
|
||||
{
|
||||
char tab[4];
|
||||
float n;
|
||||
} castUnion;
|
||||
|
||||
castUnion.tab[0]=data.data()[0];
|
||||
castUnion.tab[1]=data.data()[1];
|
||||
castUnion.tab[2]=data.data()[2];
|
||||
castUnion.tab[3]=data.data()[3];
|
||||
return castUnion.n;
|
||||
}
|
||||
|
||||
// Converts a string into PNet string data
|
||||
QByteArray stringToData(QString str)
|
||||
{
|
||||
QByteArray data(4,0);
|
||||
// Write the size in a Uint of variable lenght (8-32 bits)
|
||||
int i=0;
|
||||
uint num1 = (uint)str.toUtf8().size();
|
||||
while (num1 >= 0x80)
|
||||
{
|
||||
data[i] = (unsigned char)(num1 | 0x80); i++;
|
||||
num1 = num1 >> 7;
|
||||
}
|
||||
data[i]=num1;
|
||||
data.resize(i+1);
|
||||
data+=str.toUtf8();
|
||||
return data;
|
||||
}
|
||||
|
||||
QString dataToString(QByteArray data)
|
||||
{
|
||||
// Variable UInt32
|
||||
unsigned char num3;
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
int i=0;
|
||||
do
|
||||
{
|
||||
num3 = data[i]; i++;
|
||||
num |= (num3 & 0x7f) << num2;
|
||||
num2 += 7;
|
||||
} while ((num3 & 0x80) != 0);
|
||||
unsigned int strlen = (uint) num;
|
||||
|
||||
if (!strlen)
|
||||
return QString();
|
||||
|
||||
data = data.right(data.size()-i); // Remove the strlen
|
||||
data.truncate(strlen);
|
||||
return QString(data);
|
||||
}
|
||||
|
||||
float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data)
|
||||
{
|
||||
uint endvalue=0;
|
||||
uint value=0;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
endvalue = (uchar)data[0];
|
||||
goto done;
|
||||
}
|
||||
value = (uchar)data[0];
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
endvalue = (value | ((uint) ((uchar)data[1]) << 8));
|
||||
goto done;
|
||||
}
|
||||
value |= (uint) (((uchar)data[1]) << 8);
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
uint num2 = (uint) (((uchar)data[2]) << 0x10);
|
||||
endvalue = (value | num2);
|
||||
goto done;
|
||||
}
|
||||
value |= (uint) (((uchar)data[2]) << 0x10);
|
||||
numberOfBits -= 8;
|
||||
endvalue = (value | ((uint) (((uchar)data[3]) << 0x18)));
|
||||
goto done;
|
||||
|
||||
done:
|
||||
|
||||
float num = max - min;
|
||||
int num2 = (((int) 1) << numberOfBits) - 1;
|
||||
float num3 = endvalue;
|
||||
float num4 = num3 / ((float) num2);
|
||||
return (min + (num4 * num));
|
||||
}
|
||||
|
||||
QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits)
|
||||
{
|
||||
QByteArray data;
|
||||
float num = max - min;
|
||||
float num2 = (value - min) / num;
|
||||
int num3 = (((int) 1) << numberOfBits) - 1;
|
||||
uint source = num3 * num2;
|
||||
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source;
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source>>8;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source>>8;
|
||||
numberOfBits -= 8;
|
||||
if (numberOfBits <= 8)
|
||||
{
|
||||
data += (unsigned char)source>>16;
|
||||
return data;
|
||||
}
|
||||
data += (unsigned char)source>>16;
|
||||
data += (unsigned char)source>>24;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t dataToUint8(QByteArray data)
|
||||
{
|
||||
return (uint8_t)data[0];
|
||||
}
|
||||
|
||||
uint16_t dataToUint16(QByteArray data)
|
||||
{
|
||||
return ((uint16_t)(uint8_t)data[0])
|
||||
+(((uint16_t)(uint8_t)data[1])<<8);
|
||||
}
|
||||
|
||||
uint32_t dataToUint32(QByteArray data)
|
||||
{
|
||||
return ((uint32_t)(uint8_t)data[0])
|
||||
+(((uint32_t)(uint8_t)data[1])<<8)
|
||||
+(((uint32_t)(uint8_t)data[2])<<16)
|
||||
+(((uint32_t)(uint8_t)data[3])<<24);
|
||||
}
|
||||
|
||||
uint64_t dataToUint64(QByteArray data)
|
||||
{
|
||||
return ((uint64_t)(uint8_t)data[0])
|
||||
+(((uint64_t)(uint8_t)data[1])<<8)
|
||||
+(((uint64_t)(uint8_t)data[2])<<16)
|
||||
+(((uint64_t)(uint8_t)data[3])<<24)
|
||||
+(((uint64_t)(uint8_t)data[4])<<32)
|
||||
+(((uint64_t)(uint8_t)data[5])<<40)
|
||||
+(((uint64_t)(uint8_t)data[6])<<48)
|
||||
+(((uint64_t)(uint8_t)data[7])<<56);
|
||||
}
|
||||
|
||||
unsigned getVUint32Size(QByteArray data)
|
||||
{
|
||||
unsigned lensize=0;
|
||||
{
|
||||
unsigned char num3;
|
||||
do {
|
||||
num3 = data[lensize];
|
||||
lensize++;
|
||||
} while ((num3 & 0x80) != 0);
|
||||
}
|
||||
return lensize;
|
||||
}
|
||||
|
||||
QByteArray uint8ToData(uint8_t num)
|
||||
{
|
||||
QByteArray data(1,0);
|
||||
data[0] = (uint8_t)num;
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint16ToData(uint16_t num)
|
||||
{
|
||||
QByteArray data(2,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint32ToData(uint32_t num)
|
||||
{
|
||||
QByteArray data(4,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
data[2] = (uint8_t)((num>>16) & 0xFF);
|
||||
data[3] = (uint8_t)((num>>24) & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray uint64ToData(uint64_t num)
|
||||
{
|
||||
QByteArray data(8,0);
|
||||
data[0] = (uint8_t)(num & 0xFF);
|
||||
data[1] = (uint8_t)((num>>8) & 0xFF);
|
||||
data[2] = (uint8_t)((num>>16) & 0xFF);
|
||||
data[3] = (uint8_t)((num>>24) & 0xFF);
|
||||
data[4] = (uint8_t)((num>>32) & 0xFF);
|
||||
data[5] = (uint8_t)((num>>40) & 0xFF);
|
||||
data[6] = (uint8_t)((num>>48) & 0xFF);
|
||||
data[7] = (uint8_t)((num>>56) & 0xFF);
|
||||
return data;
|
||||
}
|
45
updater/serialize.h
Normal file
45
updater/serialize.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SERIALIZE_H
|
||||
#define SERIALIZE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
/// Most of those functions are unsafe unless otherwise specified
|
||||
/// Do not use them on untrusted data (e.g. check a signature first)
|
||||
|
||||
QByteArray doubleToData(double num);
|
||||
QByteArray floatToData(float num);
|
||||
float dataToFloat(QByteArray data);
|
||||
QByteArray stringToData(QString str);
|
||||
QString dataToString(QByteArray data);
|
||||
float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data);
|
||||
QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits);
|
||||
uint8_t dataToUint8(QByteArray data);
|
||||
uint16_t dataToUint16(QByteArray data);
|
||||
uint32_t dataToUint32(QByteArray data);
|
||||
uint64_t dataToUint64(QByteArray data);
|
||||
unsigned getVUint32Size(QByteArray data);
|
||||
QByteArray uint8ToData(uint8_t num);
|
||||
QByteArray uint16ToData(uint16_t num);
|
||||
QByteArray uint32ToData(uint32_t num);
|
||||
QByteArray uint64ToData(uint64_t num);
|
||||
|
||||
#endif // SERIALIZE_H
|
52
updater/settingsDir.cpp
Normal file
52
updater/settingsDir.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "settingsDir.h"
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
|
||||
const QString FILENAME = "settings.ini";
|
||||
|
||||
QString getSettingsDirPath()
|
||||
{
|
||||
if (isToxPortableEnabled())
|
||||
return ".";
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
|
||||
+ QDir::separator() + "AppData" + QDir::separator() + "Roaming" + QDir::separator() + "tox");
|
||||
#else
|
||||
return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QDir::separator() + "tox");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isToxPortableEnabled()
|
||||
{
|
||||
QFile portableSettings(FILENAME);
|
||||
if (portableSettings.exists())
|
||||
{
|
||||
QSettings ps(FILENAME, QSettings::IniFormat);
|
||||
ps.beginGroup("General");
|
||||
return ps.value("makeToxPortable", false).toBool();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
27
updater/settingsDir.h
Normal file
27
updater/settingsDir.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SETTINGSDIR_H
|
||||
#define SETTINGSDIR_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
QString getSettingsDirPath();
|
||||
|
||||
bool isToxPortableEnabled();
|
||||
|
||||
#endif // SETTINGSDIR_H
|
115
updater/update.cpp
Normal file
115
updater/update.cpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "update.h"
|
||||
#include "serialize.h"
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
unsigned char key[crypto_sign_PUBLICKEYBYTES] =
|
||||
{
|
||||
0xa5, 0x80, 0xf3, 0xb7, 0xd0, 0x10, 0xc0, 0xf9, 0xd6, 0xcf, 0x48, 0x15, 0x99, 0x70, 0x92, 0x49,
|
||||
0xf6, 0xe8, 0xe5, 0xe2, 0x6c, 0x73, 0x8c, 0x48, 0x25, 0xed, 0x01, 0x72, 0xf7, 0x6c, 0x17, 0x28
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
QList<UpdateFileMeta> genUpdateDiff(QList<UpdateFileMeta> updateFlist)
|
||||
{
|
||||
QList<UpdateFileMeta> diff;
|
||||
QList<UpdateFileMeta> localFlist = parseFlist(getLocalFlist());
|
||||
|
||||
for (UpdateFileMeta file : updateFlist)
|
||||
if (!localFlist.contains(file))
|
||||
diff += file;
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
QList<UpdateFileMeta> parseFlist(QByteArray flistData)
|
||||
{
|
||||
QList<UpdateFileMeta> 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;
|
||||
}
|
55
updater/update.h
Normal file
55
updater/update.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UPDATE_H
|
||||
#define UPDATE_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <sodium.h>
|
||||
|
||||
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<UpdateFileMeta> parseFlist(QByteArray flistData);
|
||||
/// Generates a list of files we need to update
|
||||
QList<UpdateFileMeta> genUpdateDiff(QList<UpdateFileMeta> updateFlist);
|
||||
|
||||
extern unsigned char key[crypto_sign_PUBLICKEYBYTES];
|
||||
|
||||
#endif // UPDATE_H
|
36
updater/updater.pro
Normal file
36
updater/updater.pro
Normal file
|
@ -0,0 +1,36 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# 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
|
||||
|
||||
SOURCES += main.cpp\
|
||||
widget.cpp \
|
||||
settingsDir.cpp \
|
||||
update.cpp \
|
||||
serialize.cpp
|
||||
|
||||
HEADERS += widget.h \
|
||||
settingsDir.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
|
156
updater/widget.cpp
Normal file
156
updater/widget.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "widget.h"
|
||||
#include "ui_widget.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QMessageBox>
|
||||
#include <QMetaObject>
|
||||
|
||||
#include "settingsDir.h"
|
||||
#include "update.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
const bool supported = true;
|
||||
const QString QTOX_PATH = "qtox.exe";
|
||||
#else
|
||||
const bool supported = false;
|
||||
const QString QTOX_PATH;
|
||||
#endif
|
||||
|
||||
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."));
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Widget::~Widget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Widget::setProgress(int value)
|
||||
{
|
||||
ui->progress->setValue(value);
|
||||
qApp->processEvents();
|
||||
}
|
||||
|
||||
void Widget::fatalError(QString message)
|
||||
{
|
||||
QMessageBox::critical(this,tr("Error"), message+'\n'+tr("qTox will restart now."));
|
||||
deleteUpdate();
|
||||
startQToxAndExit();
|
||||
}
|
||||
|
||||
void Widget::deleteUpdate()
|
||||
{
|
||||
QDir updateDir(getSettingsDirPath()+"/update/");
|
||||
updateDir.removeRecursively();
|
||||
}
|
||||
|
||||
void Widget::startQToxAndExit()
|
||||
{
|
||||
QProcess::startDetached(QTOX_PATH);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void Widget::update()
|
||||
{
|
||||
/// 1. Find and parse the update (0-5%)
|
||||
// Check that the dir exists
|
||||
QString updateDirStr = getSettingsDirPath()+"/update/";
|
||||
QDir updateDir(updateDirStr);
|
||||
if (!updateDir.exists())
|
||||
fatalError(tr("No update found."));
|
||||
|
||||
// Check that we have a flist and that every file on the diff exists
|
||||
QFile updateFlistFile(updateDirStr+"flist");
|
||||
if (!updateFlistFile.open(QIODevice::ReadOnly))
|
||||
fatalError(tr("The update is incomplete."));
|
||||
QByteArray updateFlistData = updateFlistFile.readAll();
|
||||
updateFlistFile.close();
|
||||
|
||||
setProgress(1);
|
||||
|
||||
QList<UpdateFileMeta> updateFlist = parseFlist(updateFlistData);
|
||||
setProgress(2);
|
||||
QList<UpdateFileMeta> diff = genUpdateDiff(updateFlist);
|
||||
setProgress(4);
|
||||
for (UpdateFileMeta fileMeta : diff)
|
||||
if (!QFile::exists(updateDirStr+fileMeta.installpath))
|
||||
fatalError(tr("The update is incomplete."));
|
||||
setProgress(5);
|
||||
|
||||
/// 2. Check the update (5-50%)
|
||||
float checkProgressStep = 45/diff.size();
|
||||
float checkProgress = 5;
|
||||
for (UpdateFileMeta fileMeta : diff)
|
||||
{
|
||||
UpdateFile file;
|
||||
file.metadata = fileMeta;
|
||||
|
||||
QFile fileFile(updateDirStr+fileMeta.installpath);
|
||||
if (!fileFile.open(QIODevice::ReadOnly))
|
||||
fatalError(tr("Update files are unreadable."));
|
||||
file.data = fileFile.readAll();
|
||||
fileFile.close();
|
||||
|
||||
if (file.data.size() != (int)fileMeta.size)
|
||||
fatalError(tr("Update files are corrupted."));
|
||||
|
||||
if (crypto_sign_verify_detached(file.metadata.sig, (unsigned char*)file.data.data(),
|
||||
file.data.size(), key) != 0)
|
||||
fatalError(tr("Update files are corrupted."));
|
||||
|
||||
checkProgress += checkProgressStep;
|
||||
setProgress(checkProgress);
|
||||
}
|
||||
setProgress(50);
|
||||
|
||||
/// 3. Install the update (50-95%)
|
||||
float installProgressStep = 45/diff.size();
|
||||
float installProgress = 50;
|
||||
for (UpdateFileMeta fileMeta : diff)
|
||||
{
|
||||
QFile fileFile(updateDirStr+fileMeta.installpath);
|
||||
if (!fileFile.copy(fileMeta.installpath))
|
||||
fatalError(tr("Unable to copy the update's files."));
|
||||
|
||||
installProgress += installProgressStep;
|
||||
setProgress(installProgress);
|
||||
}
|
||||
setProgress(95);
|
||||
|
||||
/// 4. Delete the update (95-100%)
|
||||
deleteUpdate();
|
||||
setProgress(100);
|
||||
|
||||
/// 5. Start qTox and exit
|
||||
startQToxAndExit();
|
||||
}
|
51
updater/widget.h
Normal file
51
updater/widget.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program 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.
|
||||
This program 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 COPYING file for more details.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WIDGET_H
|
||||
#define WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class Widget;
|
||||
}
|
||||
|
||||
class Widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Widget(QWidget *parent = 0);
|
||||
~Widget();
|
||||
|
||||
// Utilities
|
||||
void setProgress(int value);
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
#endif // WIDGET_H
|
139
updater/widget.ui
Normal file
139
updater/widget.ui
Normal file
|
@ -0,0 +1,139 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Widget</class>
|
||||
<widget class="QWidget" name="Widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>401</width>
|
||||
<height>224</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>qTox Updater</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="res.qrc">
|
||||
<normaloff>:/res/qtox-256x256.png</normaloff>:/res/qtox-256x256.png</iconset>
|
||||
</property>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>13</y>
|
||||
<width>191</width>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="res.qrc">:/res/qtox-256x256.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="progress">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>206</x>
|
||||
<y>95</y>
|
||||
<width>171</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>205</x>
|
||||
<y>115</y>
|
||||
<width>171</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Updating qTox ...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>201</x>
|
||||
<y>170</y>
|
||||
<width>181</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><a href="https://tox.im">https://tox.im</a></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>200</x>
|
||||
<y>183</y>
|
||||
<width>181</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><a href="https://github.com/tux3/qtox">https://github.com/tux3/qtox</a></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>195</x>
|
||||
<y>32</y>
|
||||
<width>191</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>qTox Update</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="res.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
12
updater/windows/updater.exe.manifest
Normal file
12
updater/windows/updater.exe.manifest
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel
|
||||
level="requireAdministrator"
|
||||
uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
BIN
updater/windows/updater.ico
Normal file
BIN
updater/windows/updater.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
2
updater/windows/updater.rc
Normal file
2
updater/windows/updater.rc
Normal file
|
@ -0,0 +1,2 @@
|
|||
ID_ICON ICON DISCARDABLE "updater.ico"
|
||||
1 24 "updater.exe.manifest"
|
Loading…
Reference in New Issue
Block a user