#include #include #include #include #include #include #include #include "MainWindow.h" #include "../Common/ConfigHelper.h" #include "../Common/IntegrityHelper.h" #include "../Common/TicketHelper.h" namespace { QString configValue(const QString& key, const QString& fallback = QString()) { const QString value = ConfigHelper::instance().getValue(QString(), key).trimmed(); return value.isEmpty() ? fallback : value; } QString productCode() { return configValue(QStringLiteral("product_code"), configValue(QStringLiteral("app_id"))); } bool configFlag(const QString& key) { const QString value = configValue(key).toLower(); return value == QStringLiteral("true") || value == QStringLiteral("1") || value == QStringLiteral("yes") || value == QStringLiteral("on"); } } // namespace int main(int argc, char* argv[]) { QApplication a(argc, argv); QTranslator translator; if (translator.load(QStringLiteral(":/i18n/update-client_zh_CN.qm"))) a.installTranslator(&translator); const int elevatedWriteExitCode = ConfigHelper::runElevatedWriteCommandIfRequested(); if (elevatedWriteExitCode >= 0) return elevatedWriteExitCode; qDebug() << Qt::endl << "entered main app" << Qt::endl; ConfigHelper& config = ConfigHelper::instance(); QString launcherExecutable = config.getValue(QStringLiteral("Runtime"), QStringLiteral("launcher_executable")).trimmed(); launcherExecutable = ConfigHelper::executableNameForCurrentPlatform(launcherExecutable, QStringLiteral("Launcher")); QString ticketFilePath; QString healthFilePath; for (int i = 1; i < argc; ++i) { const QString arg(argv[i]); if (arg.startsWith(QStringLiteral("--ticket-file="))) ticketFilePath = arg.mid(QStringLiteral("--ticket-file=").size()); else if (arg.startsWith(QStringLiteral("--health-file="))) healthFilePath = arg.mid(QStringLiteral("--health-file=").size()); } QString ticketError; if (ticketFilePath.isEmpty() || !TicketHelper::consumeAndVerify(ticketFilePath, productCode(), config.getValue(QStringLiteral("Update"), QStringLiteral("device_id")), config.getValue(QStringLiteral("App"), QStringLiteral("current_version")), config.getValue(QStringLiteral("App"), QStringLiteral("launch_token")), &ticketError)) { QMessageBox::critical(nullptr, "Startup Restriction", QString("Invalid or missing one-time launch ticket: %1\nPlease use %2.") .arg(ticketError, launcherExecutable)); return -1; } const QString installRoot = config.installRoot(); if (configFlag(QStringLiteral("verify_installed_on_start"))) { IntegrityHelper integrity(installRoot); if (!integrity.verifyInstalledVersion( productCode(), config.getValue(QStringLiteral("App"), QStringLiteral("channel")), config.getValue(QStringLiteral("App"), QStringLiteral("current_version")))) { QMessageBox::critical(nullptr, "Integrity Check Failed", QString("Startup blocked because the installed files failed local Manifest verification.\n\nDetails:\n%1") .arg(integrity.errorString())); return -1; } } if (!healthFilePath.isEmpty()) { QDir().mkpath(QFileInfo(healthFilePath).path()); QSaveFile healthFile(healthFilePath); const QByteArray healthy("ok\n"); if (!healthFile.open(QIODevice::WriteOnly) || healthFile.write(healthy) != healthy.size() || !healthFile.commit()) { QMessageBox::critical(nullptr, "Startup Error", "Cannot write update health confirmation file."); return -1; } } MainWindow w; w.show(); qDebug() << "Main program MainApp is running normally"; return a.exec(); }