File indexing completed on 2024-04-21 05:50:43
0001 /* 0002 SPDX-FileCopyrightText: 2008, 2009, 2010, 2011, 2012, 2013 Rolf Eike Beer <kde@opensource.sf-tec.de> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "kgpgtextorfiletransaction.h" 0007 #include "kgpg_general_debug.h" 0008 0009 #include "gpgproc.h" 0010 0011 #include <KIO/JobTracker> 0012 #include <KIO/StoredTransferJob> 0013 #include <KIO/FileCopyJob> 0014 0015 #include <QRegularExpression> 0016 #include <QTemporaryFile> 0017 0018 KGpgTextOrFileTransaction::KGpgTextOrFileTransaction(QObject *parent, const QString &text, const bool allowChaining) 0019 : KGpgTransaction(parent, allowChaining) 0020 { 0021 setText(text); 0022 } 0023 0024 KGpgTextOrFileTransaction::KGpgTextOrFileTransaction(QObject *parent, const QList<QUrl> &files, const bool allowChaining) 0025 : KGpgTransaction(parent, allowChaining) 0026 { 0027 setUrls(files); 0028 } 0029 0030 KGpgTextOrFileTransaction::~KGpgTextOrFileTransaction() 0031 { 0032 cleanUrls(); 0033 } 0034 0035 void 0036 KGpgTextOrFileTransaction::setText(const QString &text) 0037 { 0038 m_text = text; 0039 cleanUrls(); 0040 0041 int begin = text.indexOf(QRegularExpression(QStringLiteral("^(.*\n)?-----BEGIN PGP [A-Z ]*-----\r?\n"))); 0042 if (begin < 0) 0043 return; 0044 0045 // find the end of the BEGIN PGP ... line 0046 static const QChar lf = QLatin1Char('\n'); 0047 begin = text.indexOf(lf, begin); 0048 Q_ASSERT(begin > 0); 0049 0050 // now loop until either an empty line is found (end of header) or 0051 // a line beginning with Charset is found. If the latter, use the 0052 // charset found there as hint for the following operation 0053 int nextlf; 0054 begin++; 0055 while ((nextlf = text.indexOf(lf, begin)) > 0) { 0056 static const QChar cr = QLatin1Char('\r'); 0057 if ((nextlf == begin) || ((nextlf == begin + 1) && (text[begin] == cr))) 0058 break; 0059 0060 const QString charset = QLatin1String("Charset: "); 0061 if (QStringView(text).mid(begin, charset.length()) == charset) { 0062 QString cs = text.mid(begin + charset.length(), nextlf - begin - charset.length()); 0063 if (!getProcess()->setCodec(cs.toLatin1())) 0064 qCDebug(KGPG_LOG_GENERAL) << "unsupported charset found in header" << cs; 0065 break; 0066 } 0067 begin = nextlf + 1; 0068 } 0069 0070 0071 } 0072 0073 void 0074 KGpgTextOrFileTransaction::setUrls(const QList<QUrl> &files) 0075 { 0076 m_text.clear(); 0077 m_inpfiles = files; 0078 } 0079 0080 bool 0081 KGpgTextOrFileTransaction::preStart() 0082 { 0083 QStringList locfiles; 0084 0085 for (const QUrl &url : std::as_const(m_inpfiles)) { 0086 if (url.isLocalFile()) { 0087 locfiles.append(url.toLocalFile()); 0088 } else { 0089 QTemporaryFile tmpFile; 0090 tmpFile.open(); 0091 0092 auto copyJob = KIO::file_copy(url, QUrl::fromLocalFile(tmpFile.fileName())); 0093 copyJob->exec(); 0094 if (!copyJob->error()) { 0095 tmpFile.setAutoRemove(false); 0096 m_tempfiles.append(tmpFile.fileName()); 0097 } else { 0098 m_messages.append(copyJob->errorString()); 0099 cleanUrls(); 0100 setSuccess(TS_KIO_FAILED); 0101 return false; 0102 } 0103 } 0104 } 0105 0106 if (locfiles.isEmpty() && m_tempfiles.isEmpty() && m_text.isEmpty() && !hasInputTransaction()) { 0107 setSuccess(TS_MSG_SEQUENCE); 0108 return false; 0109 } 0110 0111 QStringList args(QLatin1String("--status-fd=1")); 0112 0113 args << command(); 0114 // if the input is not stdin set command-fd so GnuPG 0115 // can ask if e.g. the file already exists 0116 bool hasCFd = !args.contains(QLatin1String("--command-fd=0")); 0117 if (!locfiles.isEmpty() || !m_tempfiles.isEmpty()) { 0118 if (!hasCFd) 0119 args << QLatin1String("--command-fd=0"); 0120 m_closeInput = false; 0121 } else if (closeInputAfterText()) { 0122 m_closeInput = true; 0123 } else { 0124 m_closeInput = hasCFd; 0125 } 0126 if (locfiles.count() + m_tempfiles.count() > 1) 0127 args << QLatin1String("--multifile"); 0128 args << locfiles << m_tempfiles; 0129 addArguments(args); 0130 0131 return true; 0132 } 0133 0134 void 0135 KGpgTextOrFileTransaction::postStart() 0136 { 0137 if (!m_text.isEmpty()){ 0138 GPGProc *proc = getProcess(); 0139 proc->write(m_text.toUtf8()); 0140 if (m_closeInput) 0141 proc->closeWriteChannel(); 0142 } 0143 } 0144 0145 bool 0146 KGpgTextOrFileTransaction::nextLine(const QString &line) 0147 { 0148 m_messages.append(line); 0149 0150 return false; 0151 } 0152 0153 void 0154 KGpgTextOrFileTransaction::finish() 0155 { 0156 if (getProcess()->exitCode() != 0) { 0157 setSuccess(TS_MSG_SEQUENCE); 0158 } 0159 } 0160 0161 const QStringList & 0162 KGpgTextOrFileTransaction::getMessages() const 0163 { 0164 return m_messages; 0165 } 0166 0167 void 0168 KGpgTextOrFileTransaction::cleanUrls() 0169 { 0170 for (const QString &u : std::as_const(m_tempfiles)) 0171 QFile::remove(u); 0172 0173 m_tempfiles.clear(); 0174 m_locfiles.clear(); 0175 m_inpfiles.clear(); 0176 } 0177 0178 const QList<QUrl> & 0179 KGpgTextOrFileTransaction::getInputFiles() const 0180 { 0181 return m_inpfiles; 0182 }