Line data Source code
1 : /*
2 : qgpgmerefreshkeysjob.cpp
3 :
4 : This file is part of qgpgme, the Qt API binding for gpgme
5 : Copyright (c) 2004 Klar�vdalens Datakonsult AB
6 : Copyright (c) 2016 Intevation GmbH
7 :
8 : QGpgME is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2 of the
11 : License, or (at your option) any later version.
12 :
13 : QGpgME is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License along
19 : with this program; if not, write to the Free Software Foundation, Inc.,
20 : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 :
22 : In addition, as a special exception, the copyright holders give
23 : permission to link the code of this program with any edition of
24 : the Qt library by Trolltech AS, Norway (or with modified versions
25 : of Qt that use the same license as Qt), and distribute linked
26 : combinations including the two. You must obey the GNU General
27 : Public License in all respects for all of the code used other than
28 : Qt. If you modify this file, you may extend this exception to
29 : your version of the file, but you are not obligated to do so. If
30 : you do not wish to do so, delete this exception statement from
31 : your version.
32 : */
33 :
34 : #define MAX_CMD_LENGTH 32768
35 :
36 : #include "qgpgmerefreshkeysjob.h"
37 :
38 : #include <QDebug>
39 : #include "gpgme_backend_debug.h"
40 :
41 : #include "context.h"
42 :
43 : #include <QByteArray>
44 : #include <QStringList>
45 :
46 : #include <gpg-error.h>
47 :
48 : #include <assert.h>
49 :
50 0 : QGpgME::QGpgMERefreshKeysJob::QGpgMERefreshKeysJob()
51 : : RefreshKeysJob(0),
52 : mProcess(0),
53 0 : mError(0)
54 : {
55 :
56 0 : }
57 :
58 0 : QGpgME::QGpgMERefreshKeysJob::~QGpgMERefreshKeysJob()
59 : {
60 :
61 0 : }
62 :
63 0 : GpgME::Error QGpgME::QGpgMERefreshKeysJob::start(const QStringList &patterns)
64 : {
65 0 : assert(mPatternsToDo.empty());
66 :
67 0 : mPatternsToDo = patterns;
68 0 : if (mPatternsToDo.empty()) {
69 0 : mPatternsToDo.push_back(QStringLiteral(" ")); // empty list means all -> mae
70 : }
71 : // sure to fail the first
72 : // startAProcess() guard clause
73 :
74 0 : return startAProcess();
75 : }
76 :
77 : #if MAX_CMD_LENGTH < 65 + 128
78 : #error MAX_CMD_LENGTH is too low
79 : #endif
80 :
81 0 : GpgME::Error QGpgME::QGpgMERefreshKeysJob::startAProcess()
82 : {
83 0 : if (mPatternsToDo.empty()) {
84 0 : return GpgME::Error();
85 : }
86 : // create and start gpgsm process:
87 0 : mProcess = new QProcess(this);
88 0 : mProcess->setObjectName(QStringLiteral("gpgsm -k --with-validation --force-crl-refresh --enable-crl-checks"));
89 :
90 : // FIXME: obbtain the path to gpgsm from gpgme, so we use the same instance.
91 0 : mProcess->setProgram(QStringLiteral("gpgsm"));
92 0 : QStringList arguments;
93 0 : arguments << QStringLiteral("-k")
94 0 : << QStringLiteral("--with-validation")
95 0 : << QStringLiteral("--force-crl-refresh")
96 0 : << QStringLiteral("--enable-crl-checks");
97 0 : unsigned int commandLineLength = MAX_CMD_LENGTH;
98 : commandLineLength -=
99 : strlen("gpgsm") + 1 + strlen("-k") + 1 +
100 : strlen("--with-validation") + 1 + strlen("--force-crl-refresh") + 1 +
101 0 : strlen("--enable-crl-checks") + 1;
102 0 : while (!mPatternsToDo.empty()) {
103 0 : const QByteArray pat = mPatternsToDo.front().toUtf8().trimmed();
104 0 : const unsigned int patLength = pat.length();
105 0 : if (patLength >= commandLineLength) {
106 0 : break;
107 : }
108 0 : mPatternsToDo.pop_front();
109 0 : if (pat.isEmpty()) {
110 0 : continue;
111 : }
112 0 : arguments << QLatin1String(pat);
113 0 : commandLineLength -= patLength + 1;
114 0 : }
115 :
116 0 : mProcess->setArguments(arguments);
117 :
118 : connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
119 0 : SLOT(slotProcessExited(int,QProcess::ExitStatus)));
120 : connect(mProcess, SIGNAL(readyReadStandardOutput()),
121 0 : SLOT(slotStdout()));
122 : connect(mProcess, &QProcess::readyReadStandardError,
123 0 : this, &QGpgMERefreshKeysJob::slotStderr);
124 :
125 0 : mProcess->start();
126 0 : if (!mProcess->waitForStarted()) {
127 0 : mError = GpgME::Error::fromCode(GPG_ERR_ENOENT, GPG_ERR_SOURCE_GPGSM); // what else?
128 0 : deleteLater();
129 0 : return mError;
130 : } else {
131 0 : return GpgME::Error();
132 0 : }
133 : }
134 :
135 0 : void QGpgME::QGpgMERefreshKeysJob::slotCancel()
136 : {
137 0 : if (mProcess) {
138 0 : mProcess->kill();
139 : }
140 0 : mProcess = 0;
141 0 : mError = GpgME::Error::fromCode(GPG_ERR_CANCELED, GPG_ERR_SOURCE_GPGSM);
142 0 : }
143 :
144 0 : void QGpgME::QGpgMERefreshKeysJob::slotStatus(QProcess *proc, const QString &type, const QStringList &args)
145 : {
146 0 : if (proc != mProcess) {
147 0 : return;
148 : }
149 0 : QStringList::const_iterator it = args.begin();
150 0 : bool ok = false;
151 :
152 0 : if (type == QLatin1String("ERROR")) {
153 :
154 0 : if (args.size() < 2) {
155 0 : qCDebug(GPGPME_BACKEND_LOG) << "not recognising ERROR with < 2 args!";
156 0 : return;
157 : }
158 0 : const int source = (*++it).toInt(&ok);
159 0 : if (!ok) {
160 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for first ERROR arg, got something else";
161 0 : return;
162 : }
163 0 : ok = false;
164 0 : const int code = (*++it).toInt(&ok);
165 0 : if (!ok) {
166 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for second ERROR arg, got something else";
167 0 : return;
168 : }
169 0 : mError = GpgME::Error::fromCode(code, source);
170 :
171 0 : } else if (type == QLatin1String("PROGRESS")) {
172 :
173 0 : if (args.size() < 4) {
174 0 : qCDebug(GPGPME_BACKEND_LOG) << "not recognising PROGRESS with < 4 args!";
175 0 : return;
176 : }
177 0 : const QString what = *++it;
178 0 : ok = false;
179 0 : (*++it).toInt(&ok);
180 0 : if (!ok) {
181 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"type\", got something else";
182 0 : return;
183 : }
184 0 : ok = false;
185 0 : const int cur = (*++it).toInt(&ok);
186 0 : if (!ok) {
187 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"cur\", got something else";
188 0 : return;
189 : }
190 0 : ok = false;
191 0 : const int total = (*++it).toInt(&ok);
192 0 : if (!ok) {
193 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"total\", got something else";
194 0 : return;
195 : }
196 : // TODO port
197 0 : Q_EMIT progress(QString(), cur, total);
198 :
199 : }
200 : }
201 :
202 0 : void QGpgME::QGpgMERefreshKeysJob::slotStderr()
203 : {
204 : // implement? or not?
205 0 : }
206 :
207 0 : void QGpgME::QGpgMERefreshKeysJob::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus)
208 : {
209 0 : if (!mError && !mPatternsToDo.empty()) {
210 0 : if (const GpgME::Error err = startAProcess()) {
211 0 : mError = err;
212 : } else {
213 0 : return;
214 0 : }
215 : }
216 :
217 0 : Q_EMIT done();
218 0 : if (!mError &&
219 0 : (exitStatus != QProcess::NormalExit || exitCode != 0)) {
220 0 : mError = GpgME::Error::fromCode(GPG_ERR_GENERAL, GPG_ERR_SOURCE_GPGSM);
221 : }
222 0 : Q_EMIT result(mError);
223 0 : deleteLater();
224 : }
225 : #include "qgpgmerefreshkeysjob.moc"
|