File indexing completed on 2024-04-14 05:43:28

0001 /*
0002     SPDX-FileCopyrightText: 2010-2022 Rolf Eike Beer <kde@opensource.sf-tec.de>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "kgpgdecrypt.h"
0007 
0008 #include "gpgproc.h"
0009 #include "kgpgsettings.h"
0010 
0011 #include <KLocalizedString>
0012 
0013 KGpgDecrypt::KGpgDecrypt(QObject *parent, const QString &text)
0014     : KGpgTextOrFileTransaction(parent, text),
0015     m_fileIndex(-1),
0016     m_plainLength(-1)
0017 {
0018 }
0019 
0020 KGpgDecrypt::KGpgDecrypt(QObject *parent, const QList<QUrl> &files)
0021     : KGpgTextOrFileTransaction(parent, files),
0022     m_fileIndex(0),
0023     m_plainLength(-1)
0024 {
0025 }
0026 
0027 KGpgDecrypt::KGpgDecrypt(QObject* parent, const QUrl& infile, const QUrl& outfile)
0028     : KGpgTextOrFileTransaction(parent, QList<QUrl>({infile})),
0029     m_fileIndex(0),
0030     m_plainLength(-1),
0031     m_outFilename(outfile.toLocalFile())
0032 {
0033 }
0034 
0035 QStringList
0036 KGpgDecrypt::command() const
0037 {
0038     QStringList ret;
0039 
0040     ret << QLatin1String("--decrypt") << QLatin1String("--command-fd=0");
0041 
0042     if (!m_outFilename.isEmpty())
0043         ret << QLatin1String("-o") << m_outFilename;
0044 
0045     ret << KGpgSettings::customDecrypt().simplified().split(QLatin1Char(' '), Qt::SkipEmptyParts);
0046 
0047     return ret;
0048 }
0049 
0050 QStringList
0051 KGpgDecrypt::decryptedText() const
0052 {
0053     QStringList result;
0054     int txtlength = 0;
0055 
0056     for (const QString &line : getMessages())
0057         if (!line.startsWith(QLatin1String("[GNUPG:] "))) {
0058             result.append(line);
0059             txtlength += line.length() + 1;
0060         }
0061 
0062     if (result.isEmpty())
0063         return result;
0064 
0065     QString last = result.last();
0066     // this may happen when the original text did not end with a newline
0067     if (last.endsWith(QLatin1String("[GNUPG:] DECRYPTION_OKAY"))) {
0068         // if GnuPG doesn't tell us the length assume that this happend
0069         // if it told us the length then check if it _really_ happend
0070         if (((m_plainLength != -1) && (txtlength != m_plainLength)) ||
0071                 (m_plainLength == -1)) {
0072             last.chop(24);
0073             result[result.count() - 1] = last;
0074         }
0075     }
0076 
0077     return result;
0078 }
0079 
0080 bool
0081 KGpgDecrypt::isEncryptedText(const QString &text, int *startPos, int *endPos)
0082 {
0083     int posStart = text.indexOf(QLatin1String("-----BEGIN PGP MESSAGE-----"));
0084     if (posStart == -1)
0085         return false;
0086 
0087     int posEnd = text.indexOf(QLatin1String("-----END PGP MESSAGE-----"), posStart);
0088     if (posEnd == -1)
0089         return false;
0090 
0091     if (startPos != nullptr)
0092         *startPos = posStart;
0093     if (endPos != nullptr)
0094         *endPos = posEnd;
0095 
0096     return true;
0097 }
0098 
0099 bool
0100 KGpgDecrypt::nextLine(const QString& line)
0101 {
0102     const QList<QUrl> &inputFiles = getInputFiles();
0103 
0104     if (line == QLatin1String("[GNUPG:] DECRYPTION_OKAY")) {
0105         // Assume Gpg decryption was successful even if gpg returns
0106         // an error code.
0107         decryptSuccess = true;
0108     } else if (!inputFiles.isEmpty()) {
0109         if (line == QLatin1String("[GNUPG:] BEGIN_DECRYPTION")) {
0110             Q_EMIT statusMessage(i18nc("Status message 'Decrypting <filename>' (operation starts)", "Decrypting %1", inputFiles.at(m_fileIndex).fileName()));
0111             Q_EMIT infoProgress(2 * m_fileIndex + 1, inputFiles.count() * 2);
0112         } else if (line == QLatin1String("[GNUPG:] END_DECRYPTION")) {
0113             Q_EMIT statusMessage(i18nc("Status message 'Decrypted <filename>' (operation was completed)", "Decrypted %1", inputFiles.at(m_fileIndex).fileName()));
0114             m_fileIndex++;
0115             Q_EMIT infoProgress(2 * m_fileIndex, inputFiles.count() * 2);
0116         }
0117     } else {
0118         if (line.startsWith(QLatin1String("[GNUPG:] PLAINTEXT_LENGTH "))) {
0119             bool ok;
0120             m_plainLength = QStringView(line).mid(26).toInt(&ok);
0121             if (!ok)
0122                 m_plainLength = -1;
0123         } else if (line == QLatin1String("[GNUPG:] BEGIN_DECRYPTION")) {
0124             // close the command channel (if any) to signal GnuPG that it
0125             // can start sending the output.
0126             getProcess()->closeWriteChannel();
0127         }
0128     }
0129 
0130     return KGpgTextOrFileTransaction::nextLine(line);
0131 }
0132 
0133 void
0134 KGpgDecrypt::finish()
0135 {
0136     if (decryptSuccess) {
0137         // Gpg error code is ignored.
0138         // https://bugs.kde.org/show_bug.cgi?id=357462
0139         setSuccess(TS_OK);
0140     } else {
0141         KGpgTextOrFileTransaction::finish();
0142     }
0143 }
0144 
0145 bool KGpgDecrypt::closeInputAfterText() const
0146 {
0147     // otherwise decryption does never start in GnuPG 2.3,
0148     // but doesn't hurt on older versions as well
0149     return true;
0150 }