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 : #ifdef HAVE_CONFIG_H
37 : #include "config.h"
38 : #endif
39 :
40 : #include "qgpgmerefreshkeysjob.h"
41 :
42 : #include <QDebug>
43 : #include "gpgme_backend_debug.h"
44 :
45 : #include "context.h"
46 :
47 : #include <QByteArray>
48 : #include <QStringList>
49 :
50 : #include <gpg-error.h>
51 :
52 : #include <assert.h>
53 :
54 0 : QGpgME::QGpgMERefreshKeysJob::QGpgMERefreshKeysJob()
55 : : RefreshKeysJob(0),
56 : mProcess(0),
57 0 : mError(0)
58 : {
59 :
60 0 : }
61 :
62 0 : QGpgME::QGpgMERefreshKeysJob::~QGpgMERefreshKeysJob()
63 : {
64 :
65 0 : }
66 :
67 0 : GpgME::Error QGpgME::QGpgMERefreshKeysJob::start(const QStringList &patterns)
68 : {
69 0 : assert(mPatternsToDo.empty());
70 :
71 0 : mPatternsToDo = patterns;
72 0 : if (mPatternsToDo.empty()) {
73 0 : mPatternsToDo.push_back(QStringLiteral(" ")); // empty list means all -> mae
74 : }
75 : // sure to fail the first
76 : // startAProcess() guard clause
77 :
78 0 : return startAProcess();
79 : }
80 :
81 : #if MAX_CMD_LENGTH < 65 + 128
82 : #error MAX_CMD_LENGTH is too low
83 : #endif
84 :
85 0 : GpgME::Error QGpgME::QGpgMERefreshKeysJob::startAProcess()
86 : {
87 0 : if (mPatternsToDo.empty()) {
88 0 : return GpgME::Error();
89 : }
90 : // create and start gpgsm process:
91 0 : mProcess = new QProcess(this);
92 0 : mProcess->setObjectName(QStringLiteral("gpgsm -k --with-validation --force-crl-refresh --enable-crl-checks"));
93 :
94 : // FIXME: obbtain the path to gpgsm from gpgme, so we use the same instance.
95 0 : mProcess->setProgram(QStringLiteral("gpgsm"));
96 0 : QStringList arguments;
97 0 : arguments << QStringLiteral("-k")
98 0 : << QStringLiteral("--with-validation")
99 0 : << QStringLiteral("--force-crl-refresh")
100 0 : << QStringLiteral("--enable-crl-checks");
101 0 : unsigned int commandLineLength = MAX_CMD_LENGTH;
102 0 : commandLineLength -=
103 : strlen("gpgsm") + 1 + strlen("-k") + 1 +
104 : strlen("--with-validation") + 1 + strlen("--force-crl-refresh") + 1 +
105 : strlen("--enable-crl-checks") + 1;
106 0 : while (!mPatternsToDo.empty()) {
107 0 : const QByteArray pat = mPatternsToDo.front().toUtf8().trimmed();
108 0 : const unsigned int patLength = pat.length();
109 0 : if (patLength >= commandLineLength) {
110 0 : break;
111 : }
112 0 : mPatternsToDo.pop_front();
113 0 : if (pat.isEmpty()) {
114 0 : continue;
115 : }
116 0 : arguments << QLatin1String(pat);
117 0 : commandLineLength -= patLength + 1;
118 : }
119 :
120 0 : mProcess->setArguments(arguments);
121 :
122 0 : connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
123 0 : SLOT(slotProcessExited(int,QProcess::ExitStatus)));
124 0 : connect(mProcess, SIGNAL(readyReadStandardOutput()),
125 0 : SLOT(slotStdout()));
126 0 : connect(mProcess, &QProcess::readyReadStandardError,
127 0 : this, &QGpgMERefreshKeysJob::slotStderr);
128 :
129 0 : mProcess->start();
130 0 : if (!mProcess->waitForStarted()) {
131 0 : mError = GpgME::Error::fromCode(GPG_ERR_ENOENT, GPG_ERR_SOURCE_GPGSM); // what else?
132 0 : deleteLater();
133 0 : return mError;
134 : } else {
135 0 : return GpgME::Error();
136 : }
137 : }
138 :
139 0 : void QGpgME::QGpgMERefreshKeysJob::slotCancel()
140 : {
141 0 : if (mProcess) {
142 0 : mProcess->kill();
143 : }
144 0 : mProcess = 0;
145 0 : mError = GpgME::Error::fromCode(GPG_ERR_CANCELED, GPG_ERR_SOURCE_GPGSM);
146 0 : }
147 :
148 0 : void QGpgME::QGpgMERefreshKeysJob::slotStatus(QProcess *proc, const QString &type, const QStringList &args)
149 : {
150 0 : if (proc != mProcess) {
151 0 : return;
152 : }
153 0 : QStringList::const_iterator it = args.begin();
154 0 : bool ok = false;
155 :
156 0 : if (type == QLatin1String("ERROR")) {
157 :
158 0 : if (args.size() < 2) {
159 0 : qCDebug(GPGPME_BACKEND_LOG) << "not recognising ERROR with < 2 args!";
160 0 : return;
161 : }
162 0 : const int source = (*++it).toInt(&ok);
163 0 : if (!ok) {
164 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for first ERROR arg, got something else";
165 0 : return;
166 : }
167 0 : ok = false;
168 0 : const int code = (*++it).toInt(&ok);
169 0 : if (!ok) {
170 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for second ERROR arg, got something else";
171 0 : return;
172 : }
173 0 : mError = GpgME::Error::fromCode(code, source);
174 :
175 0 : } else if (type == QLatin1String("PROGRESS")) {
176 :
177 0 : if (args.size() < 4) {
178 0 : qCDebug(GPGPME_BACKEND_LOG) << "not recognising PROGRESS with < 4 args!";
179 0 : return;
180 : }
181 0 : const QString what = *++it;
182 0 : ok = false;
183 0 : (*++it).toInt(&ok);
184 0 : if (!ok) {
185 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"type\", got something else";
186 0 : return;
187 : }
188 0 : ok = false;
189 0 : const int cur = (*++it).toInt(&ok);
190 0 : if (!ok) {
191 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"cur\", got something else";
192 0 : return;
193 : }
194 0 : ok = false;
195 0 : const int total = (*++it).toInt(&ok);
196 0 : if (!ok) {
197 0 : qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"total\", got something else";
198 0 : return;
199 : }
200 : // TODO port
201 0 : Q_EMIT progress(QString(), cur, total);
202 :
203 : }
204 : }
205 :
206 0 : void QGpgME::QGpgMERefreshKeysJob::slotStderr()
207 : {
208 : // implement? or not?
209 0 : }
210 :
211 0 : void QGpgME::QGpgMERefreshKeysJob::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus)
212 : {
213 0 : if (!mError && !mPatternsToDo.empty()) {
214 0 : if (const GpgME::Error err = startAProcess()) {
215 0 : mError = err;
216 : } else {
217 0 : return;
218 : }
219 : }
220 :
221 0 : Q_EMIT done();
222 0 : if (!mError &&
223 0 : (exitStatus != QProcess::NormalExit || exitCode != 0)) {
224 0 : mError = GpgME::Error::fromCode(GPG_ERR_GENERAL, GPG_ERR_SOURCE_GPGSM);
225 : }
226 0 : Q_EMIT result(mError);
227 0 : deleteLater();
228 : }
229 : #include "qgpgmerefreshkeysjob.moc"
|