1/*
2 * Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 */
19
20#include "gpgop.h"
21#include "gpgaction.h"
22#include "gpgop_p.h"
23
24namespace gpgQCAPlugin {
25
26//----------------------------------------------------------------------------
27// GpgOp
28//----------------------------------------------------------------------------
29GpgOp::Private::Private(GpgOp *_q)
30 : QObject(_q)
31 , sync(_q)
32 , q(_q)
33 , act(nullptr)
34 , waiting(false)
35{
36 reset(mode: ResetAll);
37}
38
39GpgOp::Private::~Private()
40{
41 reset(mode: ResetAll);
42}
43
44void GpgOp::Private::reset(ResetMode mode)
45{
46 if (act) {
47 act->disconnect(receiver: this);
48 act->setParent(nullptr);
49 act->deleteLater();
50
51 act = nullptr;
52 }
53
54 if (mode >= ResetSessionAndData) {
55 output = GpgAction::Output();
56 result.clear();
57 diagnosticText = QString();
58 eventList.clear();
59 }
60
61 if (mode >= ResetAll) {
62 opt_ascii = false;
63 opt_noagent = false;
64 opt_alwaystrust = false;
65 opt_pubfile = QString();
66 opt_secfile = QString();
67 }
68}
69
70void GpgOp::Private::make_act(GpgOp::Type _op)
71{
72 reset(mode: ResetSessionAndData);
73
74 op = _op;
75
76 act = new GpgAction(this);
77
78 connect(sender: act, signal: &GpgAction::readyRead, context: this, slot: &GpgOp::Private::act_readyRead);
79 connect(sender: act, signal: &GpgAction::bytesWritten, context: this, slot: &GpgOp::Private::act_bytesWritten);
80 connect(sender: act, signal: &GpgAction::needPassphrase, context: this, slot: &GpgOp::Private::act_needPassphrase);
81 connect(sender: act, signal: &GpgAction::needCard, context: this, slot: &GpgOp::Private::act_needCard);
82 connect(sender: act, signal: &GpgAction::finished, context: this, slot: &GpgOp::Private::act_finished);
83 connect(sender: act, signal: &GpgAction::readyReadDiagnosticText, context: this, slot: &GpgOp::Private::act_readyReadDiagnosticText);
84
85 act->input.bin = bin;
86 act->input.op = op;
87 act->input.opt_ascii = opt_ascii;
88 act->input.opt_noagent = opt_noagent;
89 act->input.opt_alwaystrust = opt_alwaystrust;
90 act->input.opt_pubfile = opt_pubfile;
91 act->input.opt_secfile = opt_secfile;
92}
93
94void GpgOp::Private::eventReady(const GpgOp::Event &e)
95{
96 eventList += e;
97 sync.conditionMet();
98}
99
100void GpgOp::Private::eventReady(GpgOp::Event::Type type)
101{
102 GpgOp::Event e;
103 e.type = type;
104 eventReady(e);
105}
106
107void GpgOp::Private::eventReady(GpgOp::Event::Type type, int written)
108{
109 GpgOp::Event e;
110 e.type = type;
111 e.written = written;
112 eventReady(e);
113}
114
115void GpgOp::Private::eventReady(GpgOp::Event::Type type, const QString &keyId)
116{
117 GpgOp::Event e;
118 e.type = type;
119 e.keyId = keyId;
120 eventReady(e);
121}
122
123void GpgOp::Private::act_readyRead()
124{
125 if (waiting)
126 eventReady(type: GpgOp::Event::ReadyRead);
127 else
128 emit q->readyRead();
129}
130
131void GpgOp::Private::act_bytesWritten(int bytes)
132{
133 if (waiting)
134 eventReady(type: GpgOp::Event::BytesWritten, written: bytes);
135 else
136 emit q->bytesWritten(bytes);
137}
138
139void GpgOp::Private::act_needPassphrase(const QString &keyId)
140{
141 if (waiting)
142 eventReady(type: GpgOp::Event::NeedPassphrase, keyId);
143 else
144 emit q->needPassphrase(keyId);
145}
146
147void GpgOp::Private::act_needCard()
148{
149 if (waiting)
150 eventReady(type: GpgOp::Event::NeedCard);
151 else
152 emit q->needCard();
153}
154
155void GpgOp::Private::act_readyReadDiagnosticText()
156{
157 const QString s = act->readDiagnosticText();
158 // printf("dtext ready: [%s]\n", qPrintable(s));
159 diagnosticText += s;
160
161 if (waiting)
162 eventReady(type: GpgOp::Event::ReadyReadDiagnosticText);
163 else
164 emit q->readyReadDiagnosticText();
165}
166
167void GpgOp::Private::act_finished()
168{
169#ifdef GPG_PROFILE
170 if (op == GpgOp::Encrypt)
171 printf("<< doEncrypt: %d >>\n", timer.elapsed());
172#endif
173
174 result = act->read();
175 diagnosticText += act->readDiagnosticText();
176 output = act->output;
177
178 QMap<int, QString> errmap;
179 errmap[GpgOp::ErrorProcess] = QStringLiteral("ErrorProcess");
180 errmap[GpgOp::ErrorPassphrase] = QStringLiteral("ErrorPassphrase");
181 errmap[GpgOp::ErrorFormat] = QStringLiteral("ErrorFormat");
182 errmap[GpgOp::ErrorSignerExpired] = QStringLiteral("ErrorSignerExpired");
183 errmap[GpgOp::ErrorEncryptExpired] = QStringLiteral("ErrorEncryptExpired");
184 errmap[GpgOp::ErrorEncryptUntrusted] = QStringLiteral("ErrorEncryptUntrusted");
185 errmap[GpgOp::ErrorEncryptInvalid] = QStringLiteral("ErrorEncryptInvalid");
186 errmap[GpgOp::ErrorDecryptNoKey] = QStringLiteral("ErrorDecryptNoKey");
187 errmap[GpgOp::ErrorUnknown] = QStringLiteral("ErrorUnknown");
188 if (output.success)
189 diagnosticText += QStringLiteral("GpgAction success\n");
190 else
191 diagnosticText += QStringLiteral("GpgAction error: %1\n").arg(a: errmap[output.errorCode]);
192
193 if (output.wasSigned) {
194 QString s;
195 if (output.verifyResult == GpgOp::VerifyGood)
196 s = QStringLiteral("VerifyGood");
197 else if (output.verifyResult == GpgOp::VerifyBad)
198 s = QStringLiteral("VerifyBad");
199 else
200 s = QStringLiteral("VerifyNoKey");
201 diagnosticText += QStringLiteral("wasSigned: verifyResult: %1\n").arg(a: s);
202 }
203
204 // printf("diagnosticText:\n%s", qPrintable(diagnosticText));
205
206 reset(mode: ResetSession);
207
208 if (waiting)
209 eventReady(type: GpgOp::Event::Finished);
210 else
211 emit q->finished();
212}
213
214GpgOp::GpgOp(const QString &bin, QObject *parent)
215 : QObject(parent)
216{
217 d = new Private(this);
218 d->bin = bin;
219}
220
221GpgOp::~GpgOp()
222{
223 delete d;
224}
225
226void GpgOp::reset()
227{
228 d->reset(mode: ResetAll);
229}
230
231bool GpgOp::isActive() const
232{
233 return (d->act ? true : false);
234}
235
236GpgOp::Type GpgOp::op() const
237{
238 return d->op;
239}
240
241void GpgOp::setAsciiFormat(bool b)
242{
243 d->opt_ascii = b;
244}
245
246void GpgOp::setDisableAgent(bool b)
247{
248 d->opt_noagent = b;
249}
250
251void GpgOp::setAlwaysTrust(bool b)
252{
253 d->opt_alwaystrust = b;
254}
255
256void GpgOp::setKeyrings(const QString &pubfile, const QString &secfile)
257{
258 d->opt_pubfile = pubfile;
259 d->opt_secfile = secfile;
260}
261
262void GpgOp::doCheck()
263{
264 d->make_act(op: Check);
265 d->act->start();
266}
267
268void GpgOp::doSecretKeyringFile()
269{
270 d->make_act(op: SecretKeyringFile);
271 d->act->start();
272}
273
274void GpgOp::doPublicKeyringFile()
275{
276 d->make_act(op: PublicKeyringFile);
277 d->act->start();
278}
279
280void GpgOp::doSecretKeys()
281{
282 d->make_act(op: SecretKeys);
283 d->act->start();
284}
285
286void GpgOp::doPublicKeys()
287{
288 d->make_act(op: PublicKeys);
289 d->act->start();
290}
291
292void GpgOp::doEncrypt(const QStringList &recip_ids)
293{
294#ifdef GPG_PROFILE
295 d->timer.start();
296 printf("<< doEncrypt >>\n");
297#endif
298
299 d->make_act(op: Encrypt);
300 d->act->input.recip_ids = recip_ids;
301 d->act->start();
302}
303
304void GpgOp::doDecrypt()
305{
306 d->make_act(op: Decrypt);
307 d->act->start();
308}
309
310void GpgOp::doSign(const QString &signer_id)
311{
312 d->make_act(op: Sign);
313 d->act->input.signer_id = signer_id;
314 d->act->start();
315}
316
317void GpgOp::doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids)
318{
319 d->make_act(op: SignAndEncrypt);
320 d->act->input.signer_id = signer_id;
321 d->act->input.recip_ids = recip_ids;
322 d->act->start();
323}
324
325void GpgOp::doSignClearsign(const QString &signer_id)
326{
327 d->make_act(op: SignClearsign);
328 d->act->input.signer_id = signer_id;
329 d->act->start();
330}
331
332void GpgOp::doSignDetached(const QString &signer_id)
333{
334 d->make_act(op: SignDetached);
335 d->act->input.signer_id = signer_id;
336 d->act->start();
337}
338
339void GpgOp::doVerify()
340{
341 d->make_act(op: Verify);
342 d->act->start();
343}
344
345void GpgOp::doVerifyDetached(const QByteArray &sig)
346{
347 d->make_act(op: VerifyDetached);
348 d->act->input.sig = sig;
349 d->act->start();
350}
351
352void GpgOp::doImport(const QByteArray &in)
353{
354 d->make_act(op: Import);
355 d->act->input.inkey = in;
356 d->act->start();
357}
358
359void GpgOp::doExport(const QString &key_id)
360{
361 d->make_act(op: Export);
362 d->act->input.export_key_id = key_id;
363 d->act->start();
364}
365
366void GpgOp::doDeleteKey(const QString &key_fingerprint)
367{
368 d->make_act(op: DeleteKey);
369 d->act->input.delete_key_fingerprint = key_fingerprint;
370 d->act->start();
371}
372
373#ifdef QPIPE_SECURE
374void GpgOp::submitPassphrase(const QCA::SecureArray &a)
375#else
376void GpgOp::submitPassphrase(const QByteArray &a)
377#endif
378{
379 d->act->submitPassphrase(a);
380}
381
382void GpgOp::cardOkay()
383{
384 d->act->cardOkay();
385}
386
387QByteArray GpgOp::read()
388{
389 if (d->act) {
390 return d->act->read();
391 } else {
392 const QByteArray a = d->result;
393 d->result.clear();
394 return a;
395 }
396}
397
398void GpgOp::write(const QByteArray &in)
399{
400 d->act->write(in);
401}
402
403void GpgOp::endWrite()
404{
405 d->act->endWrite();
406}
407
408QString GpgOp::readDiagnosticText()
409{
410 QString s = d->diagnosticText;
411 d->diagnosticText = QString();
412 return s;
413}
414
415GpgOp::Event GpgOp::waitForEvent(int msecs)
416{
417 if (!d->eventList.isEmpty())
418 return d->eventList.takeFirst();
419
420 if (!d->act)
421 return GpgOp::Event();
422
423 d->waiting = true;
424 d->sync.waitForCondition(msecs);
425 d->waiting = false;
426 if (!d->eventList.isEmpty())
427 return d->eventList.takeFirst();
428 else
429 return GpgOp::Event();
430}
431
432bool GpgOp::success() const
433{
434 return d->output.success;
435}
436
437GpgOp::Error GpgOp::errorCode() const
438{
439 return d->output.errorCode;
440}
441
442GpgOp::KeyList GpgOp::keys() const
443{
444 return d->output.keys;
445}
446
447QString GpgOp::keyringFile() const
448{
449 return d->output.keyringFile;
450}
451
452QString GpgOp::homeDir() const
453{
454 return d->output.homeDir;
455}
456
457QString GpgOp::encryptedToId() const
458{
459 return d->output.encryptedToId;
460}
461
462bool GpgOp::wasSigned() const
463{
464 return d->output.wasSigned;
465}
466
467QString GpgOp::signerId() const
468{
469 return d->output.signerId;
470}
471
472QDateTime GpgOp::timestamp() const
473{
474 return d->output.timestamp;
475}
476
477GpgOp::VerifyResult GpgOp::verifyResult() const
478{
479 return d->output.verifyResult;
480}
481
482}
483

source code of qca/plugins/qca-gnupg/gpgop.cpp