diff options
Diffstat (limited to 'installer/process')
| -rw-r--r-- | installer/process/installworker.cpp | 164 | ||||
| -rw-r--r-- | installer/process/installworker.h | 42 | ||||
| -rw-r--r-- | installer/process/removeworker.cpp | 95 | ||||
| -rw-r--r-- | installer/process/removeworker.h | 27 |
4 files changed, 328 insertions, 0 deletions
diff --git a/installer/process/installworker.cpp b/installer/process/installworker.cpp new file mode 100644 index 0000000..e7708ad --- /dev/null +++ b/installer/process/installworker.cpp @@ -0,0 +1,164 @@ +#include "installworker.h" + +InstallWorker::InstallWorker(QObject *parent) : QObject(parent) +{ +} + +bool InstallWorker::startWork() { + QLocalSocket* sock = new QLocalSocket(); + QString vendor, name, url, destPath, executable; + bool isStableStream = true, isGlobalInstall = true; + + QString previousToken; + for (QString arg : QApplication::arguments()) { + if (previousToken != "") { + if (previousToken == "--socket") { + sock->setServerName(arg); + } else if (previousToken == "--vendor") { + vendor = arg; + } else if (previousToken == "--name") { + name = arg; + } else if (previousToken == "--url") { + url = arg; + } else if (previousToken == "--destdir") { + destPath = arg; + } else if (previousToken == "--executable") { + executable = arg; + } + previousToken = ""; + } else { + if (arg == "--socket" || arg == "--vendor" || arg == "--name" || arg == "--url" || arg == "--destdir" || arg == "--executable") { + previousToken = arg; + } else if (arg == "--blueprint") { + isStableStream = false; + } else if (arg == "--stable") { + isStableStream = true; + } else if (arg == "--local") { + isGlobalInstall = false; + } else if (arg == "--global") { + isGlobalInstall = true; + } + } + } + + if (sock->serverName() == "") { + qDebug() << "Required argument --socket missing"; + return false; + } + + qDebug() << "Connecting to socket server..."; + sock->connectToServer(); + if (!sock->waitForConnected()) { + qDebug() << "Failed to connect to socket server"; + return false; + } + connect(sock, &QLocalSocket::disconnected, [=] { + qDebug() << "Socket closed"; + QApplication::exit(1); + }); + + if (!packageFile.open() || !packageTemporaryDir.isValid()) { + return false; + } + sock->write(QString("STATUS ").append(tr("Downloading %1...").arg(name)).append("\n").toUtf8()); + sock->write(QString("DEBUG %1").arg(packageFile.fileName()).toUtf8()); + + QNetworkRequest req(QUrl((QString) url)); + req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + req.setHeader(QNetworkRequest::UserAgentHeader, "theInstaller/1.0"); + QNetworkReply* reply = mgr.get(req); + connect(reply, &QNetworkReply::finished, [=] { + packageFile.flush(); + packageFile.seek(0); + + sock->write(QString("STATUS ").append(tr("Unpacking %1...").arg(name)).append("\n").toUtf8()); + sock->write("PROGRESS 0 0\n"); + sock->write(QString("DEBUG %1").arg(packageTemporaryDir.path()).toUtf8()); + + QDir::root().mkpath(destPath); + QDir dest(destPath); + + JlCompress::extractDir(packageFile.fileName(), destPath); + + sock->write(QString("STATUS ").append(tr("Configuring %1...").arg(name)).append("\n").toUtf8()); + + QDir startMenu; + if (isGlobalInstall) { + startMenu = QDir("C:/ProgramData/Microsoft/Windows/Start Menu/Programs"); + } else { + startMenu = QDir(QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)); + } + startMenu.mkpath(vendor + "/" + name); + startMenu.cd(vendor + "/" + name); + + QFileInfo executableFile(destPath + "/" + executable); + QFile::link(executableFile.absoluteFilePath(), startMenu.absoluteFilePath(executableFile.completeBaseName() + ".lnk")); + QFile::copy(QApplication::applicationFilePath(), dest.absoluteFilePath("uninstall.exe")); + + QJsonObject dataRoot; + dataRoot.insert("vendor", vendor); + dataRoot.insert("name", name); + dataRoot.insert("installPath", destPath); + dataRoot.insert("global", isGlobalInstall); + dataRoot.insert("appurl", url); + + //Write uninstall information to registry + QUuid uuid = QUuid::createUuid(); + dataRoot.insert("registryUuid", uuid.toString()); + /*HKEY SoftwareEntry; + HKEY hive; + LPCWSTR keyPath = (LPCWSTR) QString("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uuid.toString()).utf16(); + + if (isGlobalInstall) { + hive = HKEY_LOCAL_MACHINE; + } else { + hive = HKEY_CURRENT_USER; + } + + LSTATUS createReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, keyPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &SoftwareEntry, NULL); + if (createReturn == ERROR_SUCCESS) { + RegSetValueEx(SoftwareEntry, TEXT("DisplayName"), 0, REG_SZ, (const BYTE*) vendor.toStdString().data(), vendor.count() + 1); + + RegCloseKey(SoftwareEntry); + + sock->write(QString("DEBUG Uninstall GUID: " + uuid.toString()).toUtf8()); + } else { + sock->write(QString("ALERT " + tr("Error writing uninstall information to the registry: Error 0x%1").arg(QString::number(createReturn, 16)) + "\n").toUtf8()); + }*/ + + QSettings* settings; + if (isGlobalInstall) { + settings = new QSettings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uuid.toString(), QSettings::NativeFormat); + } else { + settings = new QSettings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uuid.toString(), QSettings::NativeFormat); + } + + settings->setValue("DisplayName", name); + settings->setValue("Publisher", vendor); + settings->setValue("Contact", vendor); + settings->setValue("ModifyPath", dest.absoluteFilePath("uninstall.exe")); + settings->setValue("UninstallString", dest.absoluteFilePath("uninstall.exe")); + settings->setValue("InstallDate", QDateTime::currentDateTime().toString("yyyymmdd")); + settings->setValue("InstallLocation", dest.path()); + settings->setValue("DisplayIcon", executableFile.absoluteFilePath() + ",0"); + settings->sync(); + settings->deleteLater(); + + QFile uninstallDataFile(dest.absoluteFilePath("uninstall.json")); + uninstallDataFile.open(QFile::WriteOnly); + uninstallDataFile.write(QJsonDocument(dataRoot).toJson()); + + sock->write("COMPLETE\n"); + sock->flush(); + sock->waitForBytesWritten(); + QApplication::exit(0); + }); + connect(reply, &QNetworkReply::readyRead, [=] { + packageFile.write(reply->readAll()); + }); + connect(reply, &QNetworkReply::downloadProgress, [=](qint64 bytesReceived, qint64 bytesTotal) { + sock->write(QString("PROGRESS %1 %2\n").arg(QString::number(bytesReceived), QString::number(bytesTotal)).toUtf8()); + }); + + return true; +} diff --git a/installer/process/installworker.h b/installer/process/installworker.h new file mode 100644 index 0000000..ea0db48 --- /dev/null +++ b/installer/process/installworker.h @@ -0,0 +1,42 @@ +#ifndef INSTALLWORKER_H +#define INSTALLWORKER_H + +#include <QObject> +#include <QTextStream> +#include <QLocalSocket> +#include <QDebug> +#include <QApplication> +#include <QThread> +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#include <QNetworkReply> +#include <QTemporaryFile> +#include <QTemporaryDir> +#include <QStandardPaths> +#include <QJsonDocument> +#include <QJsonObject> +#include <QUuid> +#include <QSettings> + +#include <quazip/JlCompress.h> + +#include <winreg.h> + +class InstallWorker : public QObject +{ + Q_OBJECT +public: + explicit InstallWorker(QObject *parent = nullptr); + +signals: + +public slots: + bool startWork(); + +private: + QNetworkAccessManager mgr; + QTemporaryFile packageFile; + QTemporaryDir packageTemporaryDir; +}; + +#endif // INSTALLWORKER_H diff --git a/installer/process/removeworker.cpp b/installer/process/removeworker.cpp new file mode 100644 index 0000000..2bca275 --- /dev/null +++ b/installer/process/removeworker.cpp @@ -0,0 +1,95 @@ +#include "removeworker.h" + +RemoveWorker::RemoveWorker(QObject *parent) : QObject(parent) +{ + +} + +bool RemoveWorker::startWork() { + QLocalSocket* sock = new QLocalSocket(); + QString metadataFilePath; + + QString previousToken; + for (QString arg : QApplication::arguments()) { + if (previousToken != "") { + if (previousToken == "--socket") { + sock->setServerName(arg); + } else if (previousToken == "--uninstallmetadata") { + metadataFilePath = arg; + } + previousToken = ""; + } else { + if (arg == "--socket" || arg == "--uninstallmetadata") { + previousToken = arg; + } + } + } + + if (sock->serverName() == "") { + qDebug() << "Required argument --socket missing"; + return false; + } + + if (metadataFilePath == "") { + qDebug() << "Required argument --uninstallmetadata missing"; + return false; + } + + qDebug() << "Connecting to socket server..."; + sock->connectToServer(); + if (!sock->waitForConnected()) { + qDebug() << "Failed to connect to socket server"; + return false; + } + connect(sock, &QLocalSocket::disconnected, [=] { + qDebug() << "Socket closed"; + QApplication::exit(1); + }); + + QFile metadataFile(metadataFilePath); + metadataFile.open(QFile::ReadOnly); + QJsonObject metadata = QJsonDocument::fromJson(metadataFile.readAll()).object(); + metadataFile.close(); + + QString name = metadata.value("name").toString(); + QString vendor = metadata.value("vendor").toString(); + + sock->write(QString("STATUS ").append(tr("Removing %1...").arg(name)).append("\n").toUtf8()); + + //Remove Start menu entry + QDir startMenu; + if (metadata.value("global").toBool()) { + startMenu = QDir("C:/ProgramData/Microsoft/Windows/Start Menu/Programs"); + } else { + startMenu = QDir(QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)); + } + startMenu.cd(vendor + "/" + name); + startMenu.removeRecursively(); + startMenu.cdUp(); + if (startMenu.entryList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs).count() == 0) { + startMenu.removeRecursively(); + } + + //Remove items in installation directory + QDir dest(metadata.value("installPath").toString()); + dest.removeRecursively(); + + //Remove registry entry + + QSettings* settings; + if (metadata.value("global").toBool()) { + settings = new QSettings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", QSettings::NativeFormat); + } else { + settings = new QSettings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", QSettings::NativeFormat); + } + settings->remove(metadata.value("registryUuid").toString()); + settings->sync(); + + sock->write("COMPLETE\n"); + sock->flush(); + sock->waitForBytesWritten(); + QTimer::singleShot(0, [=] { + QApplication::exit(0); + }); + return 0; +} diff --git a/installer/process/removeworker.h b/installer/process/removeworker.h new file mode 100644 index 0000000..9a73316 --- /dev/null +++ b/installer/process/removeworker.h @@ -0,0 +1,27 @@ +#ifndef REMOVEWORKER_H +#define REMOVEWORKER_H + +#include <QObject> +#include <QLocalSocket> +#include <QApplication> +#include <QFile> +#include <QJsonDocument> +#include <QJsonObject> +#include <QDir> +#include <QTimer> +#include <QStandardPaths> +#include <QSettings> + +class RemoveWorker : public QObject +{ + Q_OBJECT +public: + explicit RemoveWorker(QObject *parent = nullptr); + +signals: + +public slots: + bool startWork(); +}; + +#endif // REMOVEWORKER_H |
