diff --git a/src/main.cpp b/src/main.cpp index f659e5f0b..8daa29247 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,279 +1,284 @@ /* main.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2001, 2002, 2004, 2008 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "aboutdata.h" #include "kleopatraapplication.h" #include "mainwindow.h" #include "accessibility/accessiblewidgetfactory.h" #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #include #endif #include #include #include #include #include "utils/kuniqueservice.h" #include "utils/userinfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kleopatra_debug.h" #include "kleopatra_options.h" #include #include #include #include #include // for Qt::escape #include #include #include #include #include #include #include #include #include #include #include static bool selfCheck() { Kleo::Commands::SelfTestCommand cmd(nullptr); cmd.setAutoDelete(false); cmd.setAutomaticMode(true); QEventLoop loop; QObject::connect(&cmd, &Kleo::Commands::SelfTestCommand::finished, &loop, &QEventLoop::quit); QTimer::singleShot(0, &cmd, &Kleo::Command::start); // start() may Q_EMIT finished()... loop.exec(); if (cmd.isCanceled()) { return false; } else { return true; } } static void fillKeyCache(Kleo::UiServer *server) { auto cmd = new Kleo::ReloadKeysCommand(nullptr); QObject::connect(cmd, SIGNAL(finished()), server, SLOT(enableCryptoCommands())); cmd->start(); } int main(int argc, char **argv) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); #endif KleopatraApplication app(argc, argv); KCrash::initialize(); QAccessible::installFactory(Kleo::accessibleWidgetFactory); QElapsedTimer timer; timer.start(); // Initialize GpgME { const GpgME::Error gpgmeInitError = GpgME::initializeLibrary(0); if (gpgmeInitError) { KMessageBox::error(nullptr, xi18nc("@info", "The version of the GpgME library you are running against " "is older than the one that the GpgME++ library was built against." "Kleopatra will not function in this setting." "Please ask your administrator for help in resolving this issue."), i18nc("@title", "GpgME Too Old")); return EXIT_FAILURE; } qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: GPGME Initialized"; } KLocalizedString::setApplicationDomain("kleopatra"); AboutData aboutData; KAboutData::setApplicationData(aboutData); if (Kleo::userIsElevated()) { /* This is a safeguard against bugreports that something fails because * of permission problems on windows. Some users still have the Windows * Vista behavior of running things as Administrator. This can break * GnuPG in horrible ways for example if a stale lockfile is left that * can't be removed without another elevation. * * Note: This is not the same as running as root on Linux. Elevated means * that you are temporarily running with the "normal" user environment but * with elevated permissions. * */ if (KMessageBox::warningContinueCancel(nullptr, xi18nc("@info", "Kleopatra cannot be run as adminstrator without " "breaking file permissions in the GnuPG data folder." "To manage keys for other users please manage them as a normal user and " "copy the AppData\\Roaming\\gnupg directory with proper permissions.") + xi18n("Are you sure that you want to continue?"), i18nc("@title", "Running as Administrator")) != KMessageBox::Continue) { return EXIT_FAILURE; } qCWarning(KLEOPATRA_LOG) << "User is running with administrative permissions."; } KUniqueService service; QObject::connect(&service, &KUniqueService::activateRequested, &app, &KleopatraApplication::slotActivateRequested); QObject::connect(&app, &KleopatraApplication::setExitValue, &service, [&service](int i) { service.setExitValue(i); }); // Delay init after KUniqueservice call as this might already // have terminated us and so we can avoid overhead (e.g. keycache // setup / systray icon). qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: Service created"; app.init(); qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: Application initialized"; QCommandLineParser parser; aboutData.setupCommandLine(&parser); kleopatra_options(&parser); parser.process(QApplication::arguments()); aboutData.processCommandLine(&parser); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) Kdelibs4ConfigMigrator migrate(QStringLiteral("kleopatra")); migrate.setConfigFiles(QStringList() << QStringLiteral("kleopatrarc") << QStringLiteral("libkleopatrarc")); migrate.setUiFiles(QStringList() << QStringLiteral("kleopatra.rc")); migrate.migrate(); #endif qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: Application created"; { const unsigned int threads = QThreadPool::globalInstance()->maxThreadCount(); QThreadPool::globalInstance()->setMaxThreadCount(qMax(2U, threads)); } Kleo::ChecksumDefinition::setInstallPath(Kleo::gpg4winInstallPath()); Kleo::ArchiveDefinition::setInstallPath(Kleo::gnupgInstallPath()); int rc; Kleo::UiServer *server = nullptr; try { server = new Kleo::UiServer(parser.value(QStringLiteral("uiserver-socket"))); qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: UiServer created"; QObject::connect(server, &Kleo::UiServer::startKeyManagerRequested, &app, &KleopatraApplication::openOrRaiseMainWindow); QObject::connect(server, &Kleo::UiServer::startConfigDialogRequested, &app, &KleopatraApplication::openOrRaiseConfigDialog); #define REGISTER( Command ) server->registerCommandFactory( std::shared_ptr( new Kleo::GenericAssuanCommandFactory ) ) REGISTER(CreateChecksumsCommand); REGISTER(DecryptCommand); REGISTER(DecryptFilesCommand); REGISTER(DecryptVerifyFilesCommand); REGISTER(EchoCommand); REGISTER(EncryptCommand); REGISTER(EncryptFilesCommand); REGISTER(EncryptSignFilesCommand); REGISTER(ImportFilesCommand); REGISTER(PrepEncryptCommand); REGISTER(PrepSignCommand); REGISTER(SelectCertificateCommand); REGISTER(SignCommand); REGISTER(SignEncryptFilesCommand); REGISTER(SignFilesCommand); REGISTER(VerifyChecksumsCommand); REGISTER(VerifyCommand); REGISTER(VerifyFilesCommand); #undef REGISTER server->start(); qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: UiServer started"; } catch (const std::exception &e) { qCDebug(KLEOPATRA_LOG) << "Failed to start UI Server: " << e.what(); #ifdef Q_OS_WIN - // Once there actually is a plugin for other systems then Windows this - // error should probably be shown, too. But currently only Windows users need - // to care. + // We should probably change the UIServer to be only run on Windows at all because + // only the Windows Explorer Plugin uses it. But the plan of GnuPG devs as of 2022 is to + // change the Windows Explorer Plugin to use the command line and then remove the + // UiServer for everyone. QMessageBox::information(nullptr, i18n("GPG UI Server Error"), - i18n("The Kleopatra GPG UI Server Module could not be initialized.
" - "The error given was: %1
" - "This likely means that there is a problem with your installation. Try reinstalling or " - "contact your Administrator for support.
", - QString::fromUtf8(e.what()).toHtmlEscaped())); + i18nc("This error message is only shown on Windows when the socket to communicate with " + "Windows Explorer could not be created. This often times means that the whole installation is " + "buggy. e.g. GnuPG is not installed at all.", + "The Kleopatra Windows Explorer Module could not be initialized.
" + "The error given was: %1
" + "This likely means that there is a problem with your installation. Try reinstalling or " + "contact your Administrator for support.
" + "You can try to continue to use Kleopatra but there might be other problems.
", + QString::fromUtf8(e.what()).toHtmlEscaped())); #endif } const bool daemon = parser.isSet(QStringLiteral("daemon")); if (!daemon && app.isSessionRestored()) { app.restoreMainWindow(); } if (!selfCheck()) { return EXIT_FAILURE; } qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: SelfCheck completed"; if (server) { fillKeyCache(server); } #ifndef QT_NO_SYSTEMTRAYICON app.startMonitoringSmartCard(); #endif app.setIgnoreNewInstance(false); if (!daemon) { const QString err = app.newInstance(parser); if (!err.isEmpty()) { std::cerr << i18n("Invalid arguments: %1", err).toLocal8Bit().constData() << "\n"; return EXIT_FAILURE; } qCDebug(KLEOPATRA_LOG) << "Startup timing:" << timer.elapsed() << "ms elapsed: new instance created"; } rc = app.exec(); app.setIgnoreNewInstance(true); QObject::disconnect(server, &Kleo::UiServer::startKeyManagerRequested, &app, &KleopatraApplication::openOrRaiseMainWindow); QObject::disconnect(server, &Kleo::UiServer::startConfigDialogRequested, &app, &KleopatraApplication::openOrRaiseConfigDialog); if (server) { server->stop(); server->waitForStopped(); delete server; } return rc; }