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