File indexing completed on 2024-04-21 04:57:02

0001 /**************************************************************************
0002  *   Copyright (C) 2009-2011 Matthias Fuchs <mat69@gmx.net>                *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; if not, write to the                         *
0016  *   Free Software Foundation, Inc.,                                       *
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0018  ***************************************************************************/
0019 
0020 #include "keydownloader.h"
0021 #include "settings.h"
0022 #include "signature_p.h"
0023 
0024 #include "kget_debug.h"
0025 #include <KIO/StoredTransferJob>
0026 #include <KLocalizedString>
0027 #include <KMessageBox>
0028 #include <QDebug>
0029 
0030 #ifdef HAVE_QGPGME
0031 #include <gpgme++/context.h>
0032 #include <gpgme++/data.h>
0033 #include <gpgme++/importresult.h>
0034 #include <qgpgme/dataprovider.h>
0035 #endif
0036 
0037 KeyDownloader::KeyDownloader(QObject *parent)
0038     : QObject(parent)
0039 {
0040 }
0041 
0042 bool KeyDownloader::isValid() const
0043 {
0044 #ifdef HAVE_QGPGME
0045     return true;
0046 #else // HAVE_QGPGME
0047     return false;
0048 #endif // HAVE_QGPGME
0049 }
0050 
0051 void KeyDownloader::downloadKey(QString fingerprint, Signature *sig)
0052 {
0053     downloadKey(fingerprint, sig, false);
0054 }
0055 
0056 void KeyDownloader::downloadKey(QString fingerprint, Signature *sig, bool mirrorFailed)
0057 {
0058     if (fingerprint.isEmpty() || (!sig && !mirrorFailed)) {
0059         return;
0060     }
0061 
0062     if (!fingerprint.startsWith(QLatin1String("0x"))) {
0063         fingerprint = "0x" + fingerprint;
0064     }
0065 
0066     if (m_downloading.contains(fingerprint) && !mirrorFailed) {
0067         if (!m_downloading.contains(fingerprint, sig)) {
0068             m_downloading.insert(fingerprint, sig);
0069         }
0070     } else {
0071         const QStringList servers = Settings::signatureKeyServers();
0072         if (!servers.count()) {
0073             KMessageBox::error(nullptr, i18n("No server for downloading keys is specified in settings. Downloading aborted."), i18n("No key server"));
0074             return;
0075         }
0076 
0077         QString mirror;
0078         if (mirrorFailed) {
0079             const QStringList failedMirrors = m_triedMirrors.values(fingerprint);
0080             for (int i = 0; i < servers.count(); ++i) {
0081                 if (!m_triedMirrors.contains(fingerprint, servers.at(i))) {
0082                     mirror = servers.at(i);
0083                     break;
0084                 }
0085             }
0086         } else {
0087             mirror = servers.first();
0088         }
0089 
0090         if (mirror.isEmpty()) {
0091             KMessageBox::error(nullptr,
0092                                i18n("No useful key server found, key not downloaded. Add more servers to the settings or restart KGet and retry downloading."),
0093                                i18n("No key server"));
0094             return;
0095         }
0096 
0097         m_triedMirrors.insert(fingerprint, mirror);
0098         if (!mirrorFailed) {
0099             m_downloading.insert(fingerprint, sig);
0100         }
0101 
0102         QUrl url;
0103         url.setPath(mirror + "pks/lookup");
0104         url.setQuery("op=get&options=mr&search=" + fingerprint);
0105         url.setPort(11371);
0106 
0107         qCDebug(KGET_DEBUG) << "Downloading:" << url;
0108 
0109         KIO::StoredTransferJob *job = KIO::storedGet(url, KIO::Reload, KIO::HideProgressInfo);
0110         m_jobs[job] = fingerprint;
0111         connect(job, &KJob::finished, this, &KeyDownloader::slotDownloaded);
0112     }
0113 }
0114 
0115 void KeyDownloader::slotDownloaded(KJob *job)
0116 {
0117 #ifdef HAVE_QGPGME
0118     if (!m_jobs.contains(job)) {
0119         return;
0120     }
0121 
0122     const QString fingerprint = m_jobs[job];
0123     auto *transferJob = static_cast<KIO::StoredTransferJob *>(job);
0124 
0125     if (transferJob->isErrorPage()) {
0126         qCDebug(KGET_DEBUG) << "Mirror did not work, try another one.";
0127         downloadKey(fingerprint, nullptr, true);
0128         return;
0129     }
0130 
0131     QByteArray data = transferJob->data();
0132     if (data.isEmpty()) {
0133         qCDebug(KGET_DEBUG) << "Downloaded data is empty.";
0134         downloadKey(fingerprint, nullptr, true);
0135         return;
0136     }
0137 
0138     const int indexStart = data.indexOf("<pre>");
0139     const int indexEnd = data.indexOf("</pre>", indexStart);
0140     if ((indexStart == -1) || (indexEnd == -1)) {
0141         qCDebug(KGET_DEBUG) << "Could not find a key.";
0142         downloadKey(fingerprint, nullptr, true);
0143         return;
0144     }
0145 
0146     data = data.mid(indexStart + 6, indexEnd - indexStart - 6);
0147 
0148     GpgME::initializeLibrary();
0149     GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
0150     if (err) {
0151         qCDebug(KGET_DEBUG) << "Problem checking the engine.";
0152         return;
0153     }
0154 
0155     QScopedPointer<GpgME::Context> context(GpgME::Context::createForProtocol(GpgME::OpenPGP));
0156     if (!context.data()) {
0157         qCDebug(KGET_DEBUG) << "Could not create context.";
0158         return;
0159     }
0160 
0161     QGpgME::QByteArrayDataProvider keyBA(data);
0162     GpgME::Data key(&keyBA);
0163     GpgME::ImportResult importResult = context->importKeys(key);
0164     err = importResult.error();
0165     if (err) {
0166         qCDebug(KGET_DEBUG) << "Error while importing key.";
0167         ;
0168         return;
0169     }
0170 
0171     qCDebug(KGET_DEBUG) << "Key downloaded, notifying requesters.";
0172 
0173     QList<Signature *> sigs = m_downloading.values(fingerprint);
0174     foreach (Signature *sig, sigs) {
0175         sig->d->signatureDownloaded();
0176     }
0177     m_downloading.remove(fingerprint);
0178 #else // HAVE_QGPGME
0179     Q_UNUSED(job)
0180     qCWarning(KGET_DEBUG) << "No QGPGME support.";
0181 #endif // HAVE_QGPGME
0182 }
0183 
0184 #include "moc_keydownloader.cpp"