File indexing completed on 2023-12-03 09:19:03

0001 /*
0002     SPDX-FileCopyrightText: 2002 Jean-Baptiste Mardelle <bj@altern.org>
0003     SPDX-FileCopyrightText: 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Rolf Eike Beer <kde@opensource.sf-tec.de>
0004     SPDX-FileCopyrightText: 2016 Andrius Štikonas <andrius@stikonas.eu>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "kgpg.h"
0009 
0010 #include "gpgproc.h"
0011 #include "kgpgsettings.h"
0012 #include "keysmanager.h"
0013 #include "kgpg_interface.h"
0014 #include "kgpgexternalactions.h"
0015 #include "kgpginterface.h"
0016 #include "core/images.h"
0017 #include "editor/kgpgeditor.h"
0018 #include "transactions/kgpgimport.h"
0019 
0020 #include <QCommandLineOption>
0021 #include <QCommandLineParser>
0022 #include <QFile>
0023 #include <QMimeDatabase>
0024 #include <QMimeType>
0025 #include <QTextStream>
0026 
0027 #include <KMessageBox>
0028 #include <KWindowSystem>
0029 
0030 using namespace KgpgCore;
0031 
0032 KGpgApp::KGpgApp(int &argc, char **argv)
0033              : QApplication(argc, argv),
0034          w(nullptr),
0035          s_keyManager(nullptr)
0036 {
0037 }
0038 
0039 KGpgApp::~KGpgApp()
0040 {
0041     delete s_keyManager;
0042 }
0043 
0044 void KGpgApp::slotHandleQuit()
0045 {
0046     s_keyManager->saveToggleOpts();
0047     quit();
0048 }
0049 
0050 void KGpgApp::assistantOver(const QString &defaultKeyId)
0051 {
0052     if (!defaultKeyId.isEmpty())
0053         s_keyManager->slotSetDefaultKey(defaultKeyId);
0054 
0055     s_keyManager->show();
0056     s_keyManager->raise();
0057 }
0058 
0059 bool KGpgApp::newInstance()
0060 {
0061     const QString gpgError = GPGProc::getGpgStartupError(KGpgSettings::gpgBinaryPath());
0062     if (!gpgError.isEmpty()) {
0063                 KMessageBox::detailedError(nullptr, i18n("GnuPG failed to start.<br />You must fix the GnuPG error first before running KGpg."), gpgError, i18n("GnuPG error"));
0064         QApplication::quit();
0065         return false;
0066     }
0067 
0068     s_keyManager = new KeysManager();
0069 
0070     w = new KGpgExternalActions(s_keyManager, s_keyManager->getModel());
0071 
0072     connect(s_keyManager, &KeysManager::readAgainOptions, w, &KGpgExternalActions::readOptions);
0073     connect(w, &KGpgExternalActions::updateDefault, this, &KGpgApp::assistantOver);
0074     connect(w, &KGpgExternalActions::createNewKey, s_keyManager, &KeysManager::slotGenerateKey);
0075 
0076     const QString gpgPath = KGpgSettings::gpgConfigPath();
0077 
0078     if (!gpgPath.isEmpty()) {
0079         const int gpgver = GPGProc::gpgVersion(GPGProc::gpgVersionString(KGpgSettings::gpgBinaryPath()));
0080 
0081         // Warn if sign of a properly running gpg-agent cannot be determined
0082         // The environment variable has been removed in GnuPG 2.1, the agent is started internally by
0083         // any program part of GnuPG that needs it, so simply assume everything is fine.
0084         if ((gpgver < 0x20100) && KgpgInterface::getGpgBoolSetting(QLatin1String("use-agent"), gpgPath) &&
0085                 qEnvironmentVariableIsEmpty("GPG_AGENT_INFO"))
0086                         KMessageBox::error(nullptr, i18n("<qt>The use of <b>GnuPG Agent</b> is enabled in GnuPG's configuration file (%1).<br />"
0087                 "However, the agent does not seem to be running. This could result in problems with signing/decryption.<br />"
0088                 "Please disable GnuPG Agent from KGpg settings, or fix the agent.</qt>", gpgPath));
0089     }
0090 
0091     return true;
0092 }
0093 
0094 void KGpgApp::handleArguments(const QCommandLineParser &parser, const QDir &workingDirectory)
0095 {
0096     // parsing of command line args
0097     if (parser.isSet(QStringLiteral("k")) || (!KGpgSettings::showSystray() && parser.positionalArguments().isEmpty() && !parser.isSet(QStringLiteral("d")))) {
0098         s_keyManager->show();
0099         KWindowSystem::setOnDesktop(s_keyManager->winId(), KWindowSystem::currentDesktop());  //set on the current desktop
0100         KWindowSystem::unminimizeWindow(s_keyManager->winId());  //de-iconify window
0101         s_keyManager->raise();  // set on top
0102     } else if (parser.isSet(QStringLiteral("d"))) {
0103         s_keyManager->slotOpenEditor();
0104         s_keyManager->hide();
0105     } else {
0106         QList<QUrl> urlList;
0107 
0108         const QStringList positionalArguments = parser.positionalArguments();
0109         for (const QString &arg : positionalArguments)
0110             urlList.append(QUrl::fromLocalFile(workingDirectory.absoluteFilePath(arg)));
0111 
0112         bool directoryInside = false;
0113         for (const QUrl &url : qAsConst(urlList)) {
0114             QMimeDatabase db;
0115             if (db.mimeTypeForUrl(url).name() == QLatin1String( "inode/directory" )) {
0116                 directoryInside = true;
0117                 break;
0118             }
0119         }
0120 
0121         if (parser.isSet(QStringLiteral("e"))) {
0122             if (urlList.isEmpty())
0123                                 KMessageBox::error(nullptr, i18n("No files given."));
0124             else if (!directoryInside)
0125                 KGpgExternalActions::encryptFiles(s_keyManager, urlList);
0126             else
0127                 KGpgExternalActions::encryptFolders(s_keyManager, urlList);
0128         } else if (parser.isSet(QStringLiteral("s"))) {
0129             if (urlList.isEmpty())
0130                                 KMessageBox::error(nullptr, i18n("No files given."));
0131             else if (!directoryInside)
0132                 w->showDroppedFile(urlList.first());
0133             else
0134                                 KMessageBox::error(nullptr, i18n("Cannot decrypt and show folder."));
0135         } else if (parser.isSet(QStringLiteral("S"))) {
0136             if (urlList.isEmpty())
0137                                 KMessageBox::error(nullptr, i18n("No files given."));
0138             else if (!directoryInside)
0139                 KGpgExternalActions::signFiles(s_keyManager, urlList);
0140             else
0141                                 KMessageBox::error(nullptr, i18n("Cannot sign folder."));
0142         } else if (parser.isSet(QStringLiteral("V")) != 0) {
0143             if (urlList.isEmpty())
0144                                 KMessageBox::error(nullptr, i18n("No files given."));
0145             else if (!directoryInside)
0146                 w->verifyFile(urlList.first());
0147             else
0148                                 KMessageBox::error(nullptr, i18n("Cannot verify folder."));
0149         } else {
0150             if (directoryInside && (urlList.count() > 1)) {
0151                                 KMessageBox::error(nullptr, i18n("Unable to perform requested operation.\nPlease select only one folder, or several files, but do not mix files and folders."));
0152                 return;
0153             }
0154 
0155             if (urlList.isEmpty()) {
0156                 /* do nothing */
0157             } else if (urlList.first().fileName().endsWith(QLatin1String(".sig"))) {
0158                 w->verifyFile(urlList.first());
0159             } else {
0160                 bool haskeys = false;
0161                 bool hastext = false;
0162                 for (const QUrl &url : qAsConst(urlList)) {
0163                     QFile qfile(url.path());
0164                     if (qfile.open(QIODevice::ReadOnly)) {
0165                         const int probelen = 4096;
0166                         QTextStream t(&qfile);
0167                         QString probetext(t.read(probelen));
0168                         qfile.close();
0169 
0170                         if (KGpgImport::isKey(probetext, probetext.length() == probelen))
0171                             haskeys = true;
0172                         else
0173                             hastext = true;
0174                     }
0175                 }
0176 
0177                 if (hastext) {
0178                     KGpgExternalActions::decryptFiles(s_keyManager, urlList);
0179                 } else if (haskeys) {
0180                     s_keyManager->slotImport(urlList);
0181                 }
0182             }
0183         }
0184     }
0185 }
0186 
0187 void KGpgApp::setupCmdlineParser(QCommandLineParser& parser)
0188 {
0189     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("e"), i18n("Encrypt file")));
0190     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("k"), i18n("Open key manager")));
0191     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("d"), i18n("Open editor")));
0192     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("s"), i18n("Show encrypted file")));
0193     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("S"), i18n("Sign File")));
0194     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("V"), i18n("Verify signature")));
0195     parser.addPositionalArgument(QLatin1String("[File]"), i18n("File to open"));
0196 }
0197 
0198 void KGpgApp::slotDBusActivation(const QStringList &arguments, const QString &workingDirectory)
0199 {
0200     QCommandLineParser parser;
0201 
0202     setupCmdlineParser(parser);
0203 
0204     parser.parse(arguments);
0205 
0206     handleArguments(parser, QDir(workingDirectory));
0207 }