File indexing completed on 2024-04-28 09:46:10

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         s_keyManager->raise();  // set on top
0100     } else if (parser.isSet(QStringLiteral("d"))) {
0101         s_keyManager->slotOpenEditor();
0102         s_keyManager->hide();
0103     } else {
0104         QList<QUrl> urlList;
0105 
0106         const QStringList positionalArguments = parser.positionalArguments();
0107         for (const QString &arg : positionalArguments)
0108             urlList.append(QUrl::fromLocalFile(workingDirectory.absoluteFilePath(arg)));
0109 
0110         bool directoryInside = false;
0111         for (const QUrl &url : std::as_const(urlList)) {
0112             QMimeDatabase db;
0113             if (db.mimeTypeForUrl(url).name() == QLatin1String( "inode/directory" )) {
0114                 directoryInside = true;
0115                 break;
0116             }
0117         }
0118 
0119         if (parser.isSet(QStringLiteral("e"))) {
0120             if (urlList.isEmpty())
0121                                 KMessageBox::error(nullptr, i18n("No files given."));
0122             else if (!directoryInside)
0123                 KGpgExternalActions::encryptFiles(s_keyManager, urlList);
0124             else
0125                 KGpgExternalActions::encryptFolders(s_keyManager, urlList);
0126         } else if (parser.isSet(QStringLiteral("s"))) {
0127             if (urlList.isEmpty())
0128                                 KMessageBox::error(nullptr, i18n("No files given."));
0129             else if (!directoryInside)
0130                 w->showDroppedFile(urlList.first());
0131             else
0132                                 KMessageBox::error(nullptr, i18n("Cannot decrypt and show folder."));
0133         } else if (parser.isSet(QStringLiteral("S"))) {
0134             if (urlList.isEmpty())
0135                                 KMessageBox::error(nullptr, i18n("No files given."));
0136             else if (!directoryInside)
0137                 KGpgExternalActions::signFiles(s_keyManager, urlList);
0138             else
0139                                 KMessageBox::error(nullptr, i18n("Cannot sign folder."));
0140         } else if (parser.isSet(QStringLiteral("V")) != 0) {
0141             if (urlList.isEmpty())
0142                                 KMessageBox::error(nullptr, i18n("No files given."));
0143             else if (!directoryInside)
0144                 w->verifyFile(urlList.first());
0145             else
0146                                 KMessageBox::error(nullptr, i18n("Cannot verify folder."));
0147         } else {
0148             if (directoryInside && (urlList.count() > 1)) {
0149                                 KMessageBox::error(nullptr, i18n("Unable to perform requested operation.\nPlease select only one folder, or several files, but do not mix files and folders."));
0150                 return;
0151             }
0152 
0153             if (urlList.isEmpty()) {
0154                 /* do nothing */
0155             } else if (urlList.first().fileName().endsWith(QLatin1String(".sig"))) {
0156                 w->verifyFile(urlList.first());
0157             } else {
0158                 bool haskeys = false;
0159                 bool hastext = false;
0160                 for (const QUrl &url : std::as_const(urlList)) {
0161                     QFile qfile(url.path());
0162                     if (qfile.open(QIODevice::ReadOnly)) {
0163                         const int probelen = 4096;
0164                         QTextStream t(&qfile);
0165                         QString probetext(t.read(probelen));
0166                         qfile.close();
0167 
0168                         if (KGpgImport::isKey(probetext, probetext.length() == probelen))
0169                             haskeys = true;
0170                         else
0171                             hastext = true;
0172                     }
0173                 }
0174 
0175                 if (hastext) {
0176                     KGpgExternalActions::decryptFiles(s_keyManager, urlList);
0177                 } else if (haskeys) {
0178                     s_keyManager->slotImport(urlList);
0179                 }
0180             }
0181         }
0182     }
0183 }
0184 
0185 void KGpgApp::setupCmdlineParser(QCommandLineParser& parser)
0186 {
0187     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("e"), i18n("Encrypt file")));
0188     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("k"), i18n("Open key manager")));
0189     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("d"), i18n("Open editor")));
0190     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("s"), i18n("Show encrypted file")));
0191     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("S"), i18n("Sign File")));
0192     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("V"), i18n("Verify signature")));
0193     parser.addPositionalArgument(QLatin1String("[File]"), i18n("File to open"));
0194 }
0195 
0196 void KGpgApp::slotDBusActivation(const QStringList &arguments, const QString &workingDirectory)
0197 {
0198     QCommandLineParser parser;
0199 
0200     setupCmdlineParser(parser);
0201 
0202     parser.parse(arguments);
0203 
0204     handleArguments(parser, QDir(workingDirectory));
0205 }