Line data Source code
1 : /*
2 : context.cpp - wraps a gpgme key context
3 : Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
4 :
5 : This file is part of GPGME++.
6 :
7 : GPGME++ is free software; you can redistribute it and/or
8 : modify it under the terms of the GNU Library General Public
9 : License as published by the Free Software Foundation; either
10 : version 2 of the License, or (at your option) any later version.
11 :
12 : GPGME++ is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU Library General Public License for more details.
16 :
17 : You should have received a copy of the GNU Library General Public License
18 : along with GPGME++; see the file COPYING.LIB. If not, write to the
19 : Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 : Boston, MA 02110-1301, USA.
21 : */
22 :
23 : #include <context.h>
24 : #include <eventloopinteractor.h>
25 : #include <trustitem.h>
26 : #include <keylistresult.h>
27 : #include <keygenerationresult.h>
28 : #include <importresult.h>
29 : #include <decryptionresult.h>
30 : #include <verificationresult.h>
31 : #include <signingresult.h>
32 : #include <encryptionresult.h>
33 : #include <engineinfo.h>
34 : #include <editinteractor.h>
35 : #include <vfsmountresult.h>
36 :
37 : #include <interfaces/assuantransaction.h>
38 : #include <defaultassuantransaction.h>
39 :
40 : #include "callbacks.h"
41 : #include "data_p.h"
42 : #include "context_p.h"
43 : #include "util.h"
44 :
45 : #include <gpgme.h>
46 :
47 : #include <istream>
48 : #ifndef NDEBUG
49 : #include <iostream>
50 : using std::cerr;
51 : using std::endl;
52 : #endif
53 :
54 : #include <cassert>
55 :
56 : namespace GpgME
57 : {
58 :
59 0 : static inline unsigned int xtoi_1(const char *str)
60 : {
61 0 : const unsigned int ch = *str;
62 : const unsigned int result =
63 : ch <= '9' ? ch - '0' :
64 : ch <= 'F' ? ch - 'A' + 10 :
65 0 : /* else */ ch - 'a' + 10 ;
66 0 : return result < 16 ? result : 0 ;
67 : }
68 0 : static inline int xtoi_2(const char *str)
69 : {
70 0 : return xtoi_1(str) * 16U + xtoi_1(str + 1);
71 : }
72 :
73 0 : static void percent_unescape(std::string &s, bool plus2space)
74 : {
75 0 : std::string::iterator src = s.begin(), dest = s.begin(), end = s.end();
76 0 : while (src != end) {
77 0 : if (*src == '%' && end - src > 2) {
78 0 : *dest++ = xtoi_2(&*++src);
79 0 : src += 2;
80 0 : } else if (*src == '+' && plus2space) {
81 0 : *dest++ = ' ';
82 0 : ++src;
83 : } else {
84 0 : *dest++ = *src++;
85 : }
86 : }
87 0 : s.erase(dest, end);
88 0 : }
89 :
90 6 : void initializeLibrary()
91 : {
92 6 : gpgme_check_version(0);
93 6 : }
94 :
95 0 : Error initializeLibrary(int)
96 : {
97 0 : if (gpgme_check_version(GPGME_VERSION)) {
98 0 : return Error();
99 : } else {
100 0 : return Error::fromCode(GPG_ERR_USER_1);
101 : }
102 : }
103 :
104 22 : static void format_error(gpgme_error_t err, std::string &str)
105 : {
106 : char buffer[ 1024 ];
107 22 : gpgme_strerror_r(err, buffer, sizeof buffer);
108 22 : buffer[ sizeof buffer - 1 ] = '\0';
109 22 : str = buffer;
110 22 : }
111 :
112 0 : const char *Error::source() const
113 : {
114 0 : return gpgme_strsource((gpgme_error_t)mErr);
115 : }
116 :
117 22 : const char *Error::asString() const
118 : {
119 22 : if (mMessage.empty()) {
120 22 : format_error(static_cast<gpgme_error_t>(mErr), mMessage);
121 : }
122 22 : return mMessage.c_str();
123 : }
124 :
125 41 : int Error::code() const
126 : {
127 41 : return gpgme_err_code(mErr);
128 : }
129 :
130 0 : int Error::sourceID() const
131 : {
132 0 : return gpgme_err_source(mErr);
133 : }
134 :
135 34 : bool Error::isCanceled() const
136 : {
137 34 : return code() == GPG_ERR_CANCELED;
138 : }
139 :
140 0 : int Error::toErrno() const
141 : {
142 : //#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
143 0 : return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
144 : //#else
145 : // return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
146 : //#endif
147 : }
148 :
149 : // static
150 0 : bool Error::hasSystemError()
151 : {
152 0 : return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
153 : }
154 :
155 : // static
156 0 : void Error::setSystemError(gpg_err_code_t err)
157 : {
158 0 : setErrno(gpgme_err_code_to_errno(err));
159 0 : }
160 :
161 : // static
162 0 : void Error::setErrno(int err)
163 : {
164 0 : gpgme_err_set_errno(err);
165 0 : }
166 :
167 : // static
168 0 : Error Error::fromSystemError(unsigned int src)
169 : {
170 0 : return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror()));
171 : }
172 :
173 : // static
174 0 : Error Error::fromErrno(int err, unsigned int src)
175 : {
176 0 : return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err)));
177 : }
178 :
179 : // static
180 1 : Error Error::fromCode(unsigned int err, unsigned int src)
181 : {
182 1 : return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err)));
183 : }
184 :
185 0 : std::ostream &operator<<(std::ostream &os, const Error &err)
186 : {
187 0 : return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
188 : }
189 :
190 39 : Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
191 : {
192 39 : }
193 :
194 78 : Context::~Context()
195 : {
196 39 : delete d;
197 78 : }
198 :
199 38 : Context *Context::createForProtocol(Protocol proto)
200 : {
201 38 : gpgme_ctx_t ctx = 0;
202 38 : if (gpgme_new(&ctx) != 0) {
203 0 : return 0;
204 : }
205 :
206 38 : switch (proto) {
207 : case OpenPGP:
208 38 : if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) {
209 0 : gpgme_release(ctx);
210 0 : return 0;
211 : }
212 38 : break;
213 : case CMS:
214 0 : if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) {
215 0 : gpgme_release(ctx);
216 0 : return 0;
217 : }
218 0 : break;
219 : default:
220 0 : return 0;
221 : }
222 :
223 38 : return new Context(ctx);
224 : }
225 :
226 1 : std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error)
227 : {
228 1 : gpgme_ctx_t ctx = 0;
229 1 : if (const gpgme_error_t err = gpgme_new(&ctx)) {
230 0 : if (error) {
231 0 : *error = Error(err);
232 : }
233 0 : return std::unique_ptr<Context>();
234 : }
235 :
236 1 : switch (eng) {
237 : case AssuanEngine:
238 0 : if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) {
239 0 : gpgme_release(ctx);
240 0 : if (error) {
241 0 : *error = Error(err);
242 : }
243 0 : return std::unique_ptr<Context>();
244 : }
245 0 : break;
246 : case G13Engine:
247 0 : if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) {
248 0 : gpgme_release(ctx);
249 0 : if (error) {
250 0 : *error = Error(err);
251 : }
252 0 : return std::unique_ptr<Context>();
253 : }
254 0 : break;
255 : case SpawnEngine:
256 1 : if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) {
257 0 : gpgme_release(ctx);
258 0 : if (error) {
259 0 : *error = Error(err);
260 : }
261 0 : return std::unique_ptr<Context>();
262 : }
263 1 : break;
264 : default:
265 0 : if (error) {
266 0 : *error = Error::fromCode(GPG_ERR_INV_ARG);
267 : }
268 0 : return std::unique_ptr<Context>();
269 : }
270 :
271 1 : if (error) {
272 0 : *error = Error();
273 : }
274 :
275 1 : return std::unique_ptr<Context>(new Context(ctx));
276 : }
277 :
278 : //
279 : //
280 : // Context::Private
281 : //
282 : //
283 :
284 39 : Context::Private::Private(gpgme_ctx_t c)
285 : : ctx(c),
286 : iocbs(0),
287 : lastop(None),
288 : lasterr(GPG_ERR_NO_ERROR),
289 : lastAssuanInquireData(Data::null),
290 : lastAssuanTransaction(),
291 : lastEditInteractor(),
292 39 : lastCardEditInteractor()
293 : {
294 :
295 39 : }
296 :
297 78 : Context::Private::~Private()
298 : {
299 39 : if (ctx) {
300 39 : gpgme_release(ctx);
301 : }
302 39 : ctx = 0;
303 39 : delete iocbs;
304 39 : }
305 :
306 : //
307 : //
308 : // Context attributes:
309 : //
310 : //
311 :
312 0 : Protocol Context::protocol() const
313 : {
314 0 : gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
315 0 : switch (p) {
316 0 : case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
317 0 : case GPGME_PROTOCOL_CMS: return CMS;
318 0 : default: return UnknownProtocol;
319 : }
320 : }
321 :
322 3 : void Context::setArmor(bool useArmor)
323 : {
324 3 : gpgme_set_armor(d->ctx, int(useArmor));
325 3 : }
326 0 : bool Context::armor() const
327 : {
328 0 : return gpgme_get_armor(d->ctx);
329 : }
330 :
331 12 : void Context::setTextMode(bool useTextMode)
332 : {
333 12 : gpgme_set_textmode(d->ctx, int(useTextMode));
334 12 : }
335 0 : bool Context::textMode() const
336 : {
337 0 : return gpgme_get_textmode(d->ctx);
338 : }
339 :
340 0 : void Context::setOffline(bool useOfflineMode)
341 : {
342 0 : gpgme_set_offline(d->ctx, int(useOfflineMode));
343 0 : }
344 0 : bool Context::offline() const
345 : {
346 0 : return gpgme_get_offline(d->ctx);
347 : }
348 :
349 0 : void Context::setIncludeCertificates(int which)
350 : {
351 0 : if (which == DefaultCertificates) {
352 0 : which = GPGME_INCLUDE_CERTS_DEFAULT;
353 : }
354 0 : gpgme_set_include_certs(d->ctx, which);
355 0 : }
356 :
357 0 : int Context::includeCertificates() const
358 : {
359 0 : return gpgme_get_include_certs(d->ctx);
360 : }
361 :
362 16 : void Context::setKeyListMode(unsigned int mode)
363 : {
364 16 : gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
365 16 : }
366 :
367 2 : void Context::addKeyListMode(unsigned int mode)
368 : {
369 2 : const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
370 2 : gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
371 2 : }
372 :
373 10 : unsigned int Context::keyListMode() const
374 : {
375 10 : return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
376 : }
377 :
378 34 : void Context::setProgressProvider(ProgressProvider *provider)
379 : {
380 34 : gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider);
381 34 : }
382 0 : ProgressProvider *Context::progressProvider() const
383 : {
384 0 : void *pp = 0;
385 0 : gpgme_progress_cb_t pcb = &progress_callback;
386 0 : gpgme_get_progress_cb(d->ctx, &pcb, &pp);
387 0 : return static_cast<ProgressProvider *>(pp);
388 : }
389 :
390 9 : void Context::setPassphraseProvider(PassphraseProvider *provider)
391 : {
392 9 : gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider);
393 9 : }
394 :
395 0 : PassphraseProvider *Context::passphraseProvider() const
396 : {
397 0 : void *pp = 0;
398 0 : gpgme_passphrase_cb_t pcb = &passphrase_callback;
399 0 : gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
400 0 : return static_cast<PassphraseProvider *>(pp);
401 : }
402 :
403 0 : void Context::setManagedByEventLoopInteractor(bool manage)
404 : {
405 0 : if (!EventLoopInteractor::instance()) {
406 : #ifndef NDEBUG
407 : cerr << "Context::setManagedByEventLoopInteractor(): "
408 : "You must create an instance of EventLoopInteractor "
409 0 : "before using anything that needs one." << endl;
410 : #endif
411 0 : return;
412 : }
413 0 : if (manage) {
414 0 : EventLoopInteractor::instance()->manage(this);
415 : } else {
416 0 : EventLoopInteractor::instance()->unmanage(this);
417 : }
418 : }
419 0 : bool Context::managedByEventLoopInteractor() const
420 : {
421 0 : return d->iocbs != 0;
422 : }
423 :
424 0 : void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
425 : {
426 0 : if (!iocbs) {
427 0 : uninstallIOCallbacks();
428 0 : return;
429 : }
430 0 : gpgme_set_io_cbs(d->ctx, iocbs);
431 0 : delete d->iocbs; d->iocbs = iocbs;
432 : }
433 :
434 0 : void Context::uninstallIOCallbacks()
435 : {
436 : static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 };
437 : // io.add == 0 means disable io callbacks:
438 0 : gpgme_set_io_cbs(d->ctx, &noiocbs);
439 0 : delete d->iocbs; d->iocbs = 0;
440 0 : }
441 :
442 0 : Error Context::setLocale(int cat, const char *val)
443 : {
444 0 : return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
445 : }
446 :
447 0 : EngineInfo Context::engineInfo() const
448 : {
449 0 : return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
450 : }
451 :
452 0 : Error Context::setEngineFileName(const char *filename)
453 : {
454 0 : const char *const home_dir = engineInfo().homeDirectory();
455 0 : return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
456 : }
457 :
458 0 : Error Context::setEngineHomeDirectory(const char *home_dir)
459 : {
460 0 : const char *const filename = engineInfo().fileName();
461 0 : return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
462 : }
463 :
464 : //
465 : //
466 : // Key Management
467 : //
468 : //
469 :
470 11 : Error Context::startKeyListing(const char *pattern, bool secretOnly)
471 : {
472 11 : d->lastop = Private::KeyList;
473 11 : return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
474 : }
475 :
476 11 : Error Context::startKeyListing(const char *patterns[], bool secretOnly)
477 : {
478 11 : d->lastop = Private::KeyList;
479 : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
480 11 : if (!patterns || !patterns[0] || !patterns[1]) {
481 : // max. one pattern -> use the non-ext version
482 11 : return startKeyListing(patterns ? patterns[0] : 0, secretOnly);
483 : }
484 : #endif
485 0 : return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
486 : }
487 :
488 22 : Key Context::nextKey(GpgME::Error &e)
489 : {
490 22 : d->lastop = Private::KeyList;
491 : gpgme_key_t key;
492 22 : e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
493 22 : return Key(key, false);
494 : }
495 :
496 11 : KeyListResult Context::endKeyListing()
497 : {
498 11 : d->lasterr = gpgme_op_keylist_end(d->ctx);
499 11 : return keyListResult();
500 : }
501 :
502 11 : KeyListResult Context::keyListResult() const
503 : {
504 11 : return KeyListResult(d->ctx, Error(d->lasterr));
505 : }
506 :
507 5 : Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
508 : {
509 5 : d->lastop = Private::KeyList;
510 : gpgme_key_t key;
511 5 : e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
512 5 : return Key(key, false);
513 : }
514 :
515 0 : KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
516 : {
517 0 : d->lastop = Private::KeyGen;
518 0 : Data::Private *const dp = pubKey.impl();
519 0 : d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0);
520 0 : return KeyGenerationResult(d->ctx, Error(d->lasterr));
521 : }
522 :
523 0 : Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
524 : {
525 0 : d->lastop = Private::KeyGen;
526 0 : Data::Private *const dp = pubKey.impl();
527 0 : return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0));
528 : }
529 :
530 0 : KeyGenerationResult Context::keyGenerationResult() const
531 : {
532 0 : if (d->lastop & Private::KeyGen) {
533 0 : return KeyGenerationResult(d->ctx, Error(d->lasterr));
534 : } else {
535 0 : return KeyGenerationResult();
536 : }
537 : }
538 :
539 0 : Error Context::exportPublicKeys(const char *pattern, Data &keyData)
540 : {
541 0 : d->lastop = Private::Export;
542 0 : Data::Private *const dp = keyData.impl();
543 0 : return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
544 : }
545 :
546 0 : Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
547 : {
548 0 : d->lastop = Private::Export;
549 : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
550 0 : if (!patterns || !patterns[0] || !patterns[1]) {
551 : // max. one pattern -> use the non-ext version
552 0 : return exportPublicKeys(patterns ? patterns[0] : 0, keyData);
553 : }
554 : #endif
555 0 : Data::Private *const dp = keyData.impl();
556 0 : return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
557 : }
558 :
559 0 : Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
560 : {
561 0 : d->lastop = Private::Export;
562 0 : Data::Private *const dp = keyData.impl();
563 0 : return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
564 : }
565 :
566 0 : Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
567 : {
568 0 : d->lastop = Private::Export;
569 : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
570 0 : if (!patterns || !patterns[0] || !patterns[1]) {
571 : // max. one pattern -> use the non-ext version
572 0 : return startPublicKeyExport(patterns ? patterns[0] : 0, keyData);
573 : }
574 : #endif
575 0 : Data::Private *const dp = keyData.impl();
576 0 : return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
577 : }
578 :
579 0 : ImportResult Context::importKeys(const Data &data)
580 : {
581 0 : d->lastop = Private::Import;
582 0 : const Data::Private *const dp = data.impl();
583 0 : d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
584 0 : return ImportResult(d->ctx, Error(d->lasterr));
585 : }
586 :
587 0 : ImportResult Context::importKeys(const std::vector<Key> &kk)
588 : {
589 0 : d->lastop = Private::Import;
590 0 : d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
591 :
592 0 : bool shouldHaveResult = false;
593 0 : gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
594 0 : gpgme_key_t *keys_it = &keys[0];
595 0 : for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
596 0 : if (it->impl()) {
597 0 : *keys_it++ = it->impl();
598 : }
599 : }
600 0 : *keys_it++ = 0;
601 0 : d->lasterr = gpgme_op_import_keys(d->ctx, keys);
602 0 : shouldHaveResult = true;
603 0 : if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
604 0 : gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
605 0 : protocol() == CMS) {
606 : // ok, try the workaround (export+import):
607 0 : std::vector<const char *> fprs;
608 0 : for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
609 0 : if (const char *fpr = it->primaryFingerprint()) {
610 0 : if (*fpr) {
611 0 : fprs.push_back(fpr);
612 : }
613 0 : } else if (const char *keyid = it->keyID()) {
614 0 : if (*keyid) {
615 0 : fprs.push_back(keyid);
616 : }
617 : }
618 : }
619 0 : fprs.push_back(0);
620 0 : Data data;
621 0 : Data::Private *const dp = data.impl();
622 0 : const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
623 0 : gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
624 0 : d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0);
625 0 : gpgme_set_keylist_mode(d->ctx, oldMode);
626 0 : if (!d->lasterr) {
627 0 : data.seek(0, SEEK_SET);
628 0 : d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
629 0 : shouldHaveResult = true;
630 0 : }
631 : }
632 0 : delete[] keys;
633 0 : if (shouldHaveResult) {
634 0 : return ImportResult(d->ctx, Error(d->lasterr));
635 : } else {
636 0 : return ImportResult(Error(d->lasterr));
637 : }
638 : }
639 :
640 0 : Error Context::startKeyImport(const Data &data)
641 : {
642 0 : d->lastop = Private::Import;
643 0 : const Data::Private *const dp = data.impl();
644 0 : return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0));
645 : }
646 :
647 0 : Error Context::startKeyImport(const std::vector<Key> &kk)
648 : {
649 0 : d->lastop = Private::Import;
650 0 : gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
651 0 : gpgme_key_t *keys_it = &keys[0];
652 0 : for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
653 0 : if (it->impl()) {
654 0 : *keys_it++ = it->impl();
655 : }
656 : }
657 0 : *keys_it++ = 0;
658 0 : Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
659 0 : delete[] keys;
660 0 : return err;
661 : }
662 :
663 0 : ImportResult Context::importResult() const
664 : {
665 0 : if (d->lastop & Private::Import) {
666 0 : return ImportResult(d->ctx, Error(d->lasterr));
667 : } else {
668 0 : return ImportResult();
669 : }
670 : }
671 :
672 0 : Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
673 : {
674 0 : d->lastop = Private::Delete;
675 0 : return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
676 : }
677 :
678 0 : Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
679 : {
680 0 : d->lastop = Private::Delete;
681 0 : return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
682 : }
683 :
684 0 : Error Context::passwd(const Key &key)
685 : {
686 0 : d->lastop = Private::Passwd;
687 0 : return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
688 : }
689 :
690 0 : Error Context::startPasswd(const Key &key)
691 : {
692 0 : d->lastop = Private::Passwd;
693 0 : return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
694 : }
695 :
696 2 : Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
697 : {
698 2 : d->lastop = Private::Edit;
699 2 : d->lastEditInteractor = std::move(func);
700 2 : Data::Private *const dp = data.impl();
701 : return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
702 2 : d->lastEditInteractor.get() ? edit_interactor_callback : 0,
703 4 : d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
704 8 : dp ? dp->data : 0));
705 : }
706 :
707 0 : Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
708 : {
709 0 : d->lastop = Private::Edit;
710 0 : d->lastEditInteractor = std::move(func);
711 0 : Data::Private *const dp = data.impl();
712 : return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
713 0 : d->lastEditInteractor.get() ? edit_interactor_callback : 0,
714 0 : d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
715 0 : dp ? dp->data : 0));
716 : }
717 :
718 0 : EditInteractor *Context::lastEditInteractor() const
719 : {
720 0 : return d->lastEditInteractor.get();
721 : }
722 :
723 0 : std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
724 : {
725 0 : return std::move(d->lastEditInteractor);
726 : }
727 :
728 0 : Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
729 : {
730 0 : d->lastop = Private::CardEdit;
731 0 : d->lastCardEditInteractor = std::move(func);
732 0 : Data::Private *const dp = data.impl();
733 : return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
734 0 : d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
735 0 : d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
736 0 : dp ? dp->data : 0));
737 : }
738 :
739 0 : Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
740 : {
741 0 : d->lastop = Private::CardEdit;
742 0 : d->lastCardEditInteractor = std::move(func);
743 0 : Data::Private *const dp = data.impl();
744 : return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
745 0 : d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
746 0 : d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
747 0 : dp ? dp->data : 0));
748 : }
749 :
750 0 : EditInteractor *Context::lastCardEditInteractor() const
751 : {
752 0 : return d->lastCardEditInteractor.get();
753 : }
754 :
755 0 : std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
756 : {
757 0 : return std::move(d->lastCardEditInteractor);
758 : }
759 :
760 0 : Error Context::startTrustItemListing(const char *pattern, int maxLevel)
761 : {
762 0 : d->lastop = Private::TrustList;
763 0 : return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
764 : }
765 :
766 0 : TrustItem Context::nextTrustItem(Error &e)
767 : {
768 0 : gpgme_trust_item_t ti = 0;
769 0 : e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
770 0 : return TrustItem(ti);
771 : }
772 :
773 0 : Error Context::endTrustItemListing()
774 : {
775 0 : return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
776 : }
777 :
778 0 : static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
779 : {
780 0 : assert(opaque);
781 0 : AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
782 0 : return t->data(static_cast<const char *>(data), datalen).encodedError();
783 : }
784 :
785 0 : static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
786 : {
787 0 : assert(opaque);
788 0 : Context::Private *p = static_cast<Context::Private *>(opaque);
789 0 : AssuanTransaction *t = p->lastAssuanTransaction.get();
790 0 : assert(t);
791 0 : Error err;
792 0 : if (name) {
793 0 : p->lastAssuanInquireData = t->inquire(name, args, err);
794 : } else {
795 0 : p->lastAssuanInquireData = Data::null;
796 : }
797 0 : if (!p->lastAssuanInquireData.isNull()) {
798 0 : *r_data = p->lastAssuanInquireData.impl()->data;
799 : }
800 0 : return err.encodedError();
801 : }
802 :
803 0 : static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
804 : {
805 0 : assert(opaque);
806 0 : AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
807 0 : std::string a = args;
808 0 : percent_unescape(a, true); // ### why doesn't gpgme do this??
809 0 : return t->status(status, a.c_str()).encodedError();
810 : }
811 :
812 0 : Error Context::assuanTransact(const char *command)
813 : {
814 0 : return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
815 : }
816 :
817 0 : Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
818 : {
819 : gpgme_error_t err, operr;
820 :
821 0 : d->lastop = Private::AssuanTransact;
822 0 : d->lastAssuanTransaction = std::move(transaction);
823 0 : if (!d->lastAssuanTransaction.get()) {
824 0 : return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
825 : }
826 : err = gpgme_op_assuan_transact_ext
827 : (d->ctx,
828 : command,
829 : assuan_transaction_data_callback,
830 0 : d->lastAssuanTransaction.get(),
831 : assuan_transaction_inquire_callback,
832 : d,
833 : assuan_transaction_status_callback,
834 0 : d->lastAssuanTransaction.get(),
835 0 : &operr);
836 :
837 0 : if (!err)
838 0 : err = operr;
839 0 : d->lasterr = err;
840 :
841 0 : return Error(d->lasterr);
842 : }
843 :
844 0 : Error Context::startAssuanTransaction(const char *command)
845 : {
846 0 : return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
847 : }
848 :
849 0 : Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
850 : {
851 : gpgme_error_t err;
852 :
853 0 : d->lastop = Private::AssuanTransact;
854 0 : d->lastAssuanTransaction = std::move(transaction);
855 0 : if (!d->lastAssuanTransaction.get()) {
856 0 : return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
857 : }
858 : err = gpgme_op_assuan_transact_start
859 : (d->ctx,
860 : command,
861 : assuan_transaction_data_callback,
862 0 : d->lastAssuanTransaction.get(),
863 : assuan_transaction_inquire_callback,
864 : d,
865 : assuan_transaction_status_callback,
866 0 : d->lastAssuanTransaction.get());
867 :
868 0 : d->lasterr = err;
869 :
870 0 : return Error(d->lasterr);
871 : }
872 :
873 0 : AssuanTransaction *Context::lastAssuanTransaction() const
874 : {
875 0 : return d->lastAssuanTransaction.get();
876 : }
877 :
878 0 : std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
879 : {
880 0 : return std::move(d->lastAssuanTransaction);
881 : }
882 :
883 2 : DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
884 : {
885 2 : d->lastop = Private::Decrypt;
886 2 : const Data::Private *const cdp = cipherText.impl();
887 2 : Data::Private *const pdp = plainText.impl();
888 2 : d->lasterr = gpgme_op_decrypt(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
889 2 : return DecryptionResult(d->ctx, Error(d->lasterr));
890 : }
891 :
892 0 : Error Context::startDecryption(const Data &cipherText, Data &plainText)
893 : {
894 0 : d->lastop = Private::Decrypt;
895 0 : const Data::Private *const cdp = cipherText.impl();
896 0 : Data::Private *const pdp = plainText.impl();
897 0 : return Error(d->lasterr = gpgme_op_decrypt_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
898 : }
899 :
900 0 : DecryptionResult Context::decryptionResult() const
901 : {
902 0 : if (d->lastop & Private::Decrypt) {
903 0 : return DecryptionResult(d->ctx, Error(d->lasterr));
904 : } else {
905 0 : return DecryptionResult();
906 : }
907 : }
908 :
909 0 : VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
910 : {
911 0 : d->lastop = Private::Verify;
912 0 : const Data::Private *const sdp = signature.impl();
913 0 : const Data::Private *const tdp = signedText.impl();
914 0 : d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0);
915 0 : return VerificationResult(d->ctx, Error(d->lasterr));
916 : }
917 :
918 9 : VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
919 : {
920 9 : d->lastop = Private::Verify;
921 9 : const Data::Private *const sdp = signedData.impl();
922 9 : Data::Private *const pdp = plainText.impl();
923 9 : d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0);
924 9 : return VerificationResult(d->ctx, Error(d->lasterr));
925 : }
926 :
927 0 : Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
928 : {
929 0 : d->lastop = Private::Verify;
930 0 : const Data::Private *const sdp = signature.impl();
931 0 : const Data::Private *const tdp = signedText.impl();
932 0 : return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0));
933 : }
934 :
935 0 : Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
936 : {
937 0 : d->lastop = Private::Verify;
938 0 : const Data::Private *const sdp = signedData.impl();
939 0 : Data::Private *const pdp = plainText.impl();
940 0 : return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0));
941 : }
942 :
943 0 : VerificationResult Context::verificationResult() const
944 : {
945 0 : if (d->lastop & Private::Verify) {
946 0 : return VerificationResult(d->ctx, Error(d->lasterr));
947 : } else {
948 0 : return VerificationResult();
949 : }
950 : }
951 :
952 0 : std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
953 : {
954 0 : d->lastop = Private::DecryptAndVerify;
955 0 : const Data::Private *const cdp = cipherText.impl();
956 0 : Data::Private *const pdp = plainText.impl();
957 0 : d->lasterr = gpgme_op_decrypt_verify(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
958 : return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
959 0 : VerificationResult(d->ctx, Error(d->lasterr)));
960 : }
961 :
962 0 : Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
963 : {
964 0 : d->lastop = Private::DecryptAndVerify;
965 0 : const Data::Private *const cdp = cipherText.impl();
966 0 : Data::Private *const pdp = plainText.impl();
967 0 : return Error(d->lasterr = gpgme_op_decrypt_verify_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
968 : }
969 :
970 22 : unsigned int to_auditlog_flags(unsigned int flags)
971 : {
972 22 : unsigned int result = 0;
973 22 : if (flags & Context::HtmlAuditLog) {
974 22 : result |= GPGME_AUDITLOG_HTML;
975 : }
976 22 : if (flags & Context::AuditLogWithHelp) {
977 22 : result |= GPGME_AUDITLOG_WITH_HELP;
978 : }
979 22 : return result;
980 : }
981 :
982 0 : Error Context::startGetAuditLog(Data &output, unsigned int flags)
983 : {
984 0 : d->lastop = Private::GetAuditLog;
985 0 : Data::Private *const odp = output.impl();
986 0 : return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
987 : }
988 :
989 22 : Error Context::getAuditLog(Data &output, unsigned int flags)
990 : {
991 22 : d->lastop = Private::GetAuditLog;
992 22 : Data::Private *const odp = output.impl();
993 22 : return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
994 : }
995 :
996 6 : void Context::clearSigningKeys()
997 : {
998 6 : gpgme_signers_clear(d->ctx);
999 6 : }
1000 :
1001 6 : Error Context::addSigningKey(const Key &key)
1002 : {
1003 6 : return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
1004 : }
1005 :
1006 0 : Key Context::signingKey(unsigned int idx) const
1007 : {
1008 0 : gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
1009 0 : return Key(key, false);
1010 : }
1011 :
1012 0 : std::vector<Key> Context::signingKeys() const
1013 : {
1014 0 : std::vector<Key> result;
1015 : gpgme_key_t key;
1016 0 : for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
1017 0 : result.push_back(Key(key, false));
1018 : }
1019 0 : return result;
1020 : }
1021 :
1022 0 : void Context::clearSignatureNotations()
1023 : {
1024 0 : gpgme_sig_notation_clear(d->ctx);
1025 0 : }
1026 :
1027 0 : GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
1028 : {
1029 0 : return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
1030 : }
1031 :
1032 0 : GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
1033 : {
1034 0 : return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
1035 : }
1036 :
1037 0 : const char *Context::signaturePolicyURL() const
1038 : {
1039 0 : for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1040 0 : if (!n->name) {
1041 0 : return n->value;
1042 : }
1043 : }
1044 0 : }
1045 :
1046 0 : Notation Context::signatureNotation(unsigned int idx) const
1047 : {
1048 0 : for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1049 0 : if (n->name) {
1050 0 : if (idx-- == 0) {
1051 0 : return Notation(n);
1052 : }
1053 : }
1054 : }
1055 0 : return Notation();
1056 : }
1057 :
1058 0 : std::vector<Notation> Context::signatureNotations() const
1059 : {
1060 0 : std::vector<Notation> result;
1061 0 : for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1062 0 : if (n->name) {
1063 0 : result.push_back(Notation(n));
1064 : }
1065 : }
1066 0 : return result;
1067 : }
1068 :
1069 6 : static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
1070 : {
1071 6 : switch (mode) {
1072 : default:
1073 6 : case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
1074 0 : case Detached: return GPGME_SIG_MODE_DETACH;
1075 0 : case Clearsigned: return GPGME_SIG_MODE_CLEAR;
1076 : }
1077 : }
1078 :
1079 6 : SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
1080 : {
1081 6 : d->lastop = Private::Sign;
1082 6 : const Data::Private *const pdp = plainText.impl();
1083 6 : Data::Private *const sdp = signature.impl();
1084 6 : d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode));
1085 6 : return SigningResult(d->ctx, Error(d->lasterr));
1086 : }
1087 :
1088 0 : Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
1089 : {
1090 0 : d->lastop = Private::Sign;
1091 0 : const Data::Private *const pdp = plainText.impl();
1092 0 : Data::Private *const sdp = signature.impl();
1093 0 : return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)));
1094 : }
1095 :
1096 0 : SigningResult Context::signingResult() const
1097 : {
1098 0 : if (d->lastop & Private::Sign) {
1099 0 : return SigningResult(d->ctx, Error(d->lasterr));
1100 : } else {
1101 0 : return SigningResult();
1102 : }
1103 : }
1104 :
1105 3 : static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
1106 : {
1107 3 : unsigned int result = 0;
1108 3 : if (flags & Context::AlwaysTrust) {
1109 3 : result |= GPGME_ENCRYPT_ALWAYS_TRUST;
1110 : }
1111 3 : if (flags & Context::NoEncryptTo) {
1112 0 : result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
1113 : }
1114 3 : if (flags & Context::Prepare) {
1115 0 : result |= GPGME_ENCRYPT_PREPARE;
1116 : }
1117 3 : if (flags & Context::ExpectSign) {
1118 0 : result |= GPGME_ENCRYPT_EXPECT_SIGN;
1119 : }
1120 3 : if (flags & Context::NoCompress) {
1121 0 : result |= GPGME_ENCRYPT_NO_COMPRESS;
1122 : }
1123 3 : if (flags & Context::Symmetric) {
1124 0 : result |= GPGME_ENCRYPT_SYMMETRIC;
1125 : }
1126 3 : return static_cast<gpgme_encrypt_flags_t>(result);
1127 : }
1128 :
1129 3 : gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
1130 : {
1131 3 : if (recipients.empty()) {
1132 1 : return nullptr;
1133 : }
1134 2 : gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
1135 2 : gpgme_key_t *keys_it = ret;
1136 4 : for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1137 2 : if (it->impl()) {
1138 2 : *keys_it++ = it->impl();
1139 : }
1140 : }
1141 2 : *keys_it++ = 0;
1142 2 : return ret;
1143 : }
1144 :
1145 3 : EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1146 : {
1147 3 : d->lastop = Private::Encrypt;
1148 3 : if (flags & NoEncryptTo) {
1149 0 : return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
1150 : }
1151 3 : const Data::Private *const pdp = plainText.impl();
1152 3 : Data::Private *const cdp = cipherText.impl();
1153 3 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1154 : d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
1155 3 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1156 3 : if (keys) {
1157 2 : delete[] keys;
1158 : }
1159 3 : return EncryptionResult(d->ctx, Error(d->lasterr));
1160 : }
1161 :
1162 0 : Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
1163 : {
1164 0 : d->lastop = Private::Encrypt;
1165 0 : const Data::Private *const pdp = plainText.impl();
1166 0 : Data::Private *const cdp = cipherText.impl();
1167 : return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0,
1168 0 : pdp ? pdp->data : 0, cdp ? cdp->data : 0));
1169 : }
1170 :
1171 0 : Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1172 : {
1173 0 : d->lastop = Private::Encrypt;
1174 0 : if (flags & NoEncryptTo) {
1175 0 : return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
1176 : }
1177 0 : const Data::Private *const pdp = plainText.impl();
1178 0 : Data::Private *const cdp = cipherText.impl();
1179 0 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1180 : d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
1181 0 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1182 0 : if (keys) {
1183 0 : delete[] keys;
1184 : }
1185 0 : return Error(d->lasterr);
1186 : }
1187 :
1188 0 : EncryptionResult Context::encryptionResult() const
1189 : {
1190 0 : if (d->lastop & Private::Encrypt) {
1191 0 : return EncryptionResult(d->ctx, Error(d->lasterr));
1192 : } else {
1193 0 : return EncryptionResult();
1194 : }
1195 : }
1196 :
1197 0 : std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1198 : {
1199 0 : d->lastop = Private::SignAndEncrypt;
1200 0 : const Data::Private *const pdp = plainText.impl();
1201 0 : Data::Private *const cdp = cipherText.impl();
1202 0 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1203 : d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
1204 0 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1205 0 : if (keys) {
1206 0 : delete[] keys;
1207 : }
1208 : return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
1209 0 : EncryptionResult(d->ctx, Error(d->lasterr)));
1210 : }
1211 :
1212 0 : Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1213 : {
1214 0 : d->lastop = Private::SignAndEncrypt;
1215 0 : const Data::Private *const pdp = plainText.impl();
1216 0 : Data::Private *const cdp = cipherText.impl();
1217 0 : gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1218 : d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
1219 0 : pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1220 0 : if (keys) {
1221 0 : delete[] keys;
1222 : }
1223 0 : return Error(d->lasterr);
1224 : }
1225 :
1226 0 : Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
1227 : {
1228 0 : d->lastop = Private::CreateVFS;
1229 0 : gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
1230 0 : gpgme_key_t *keys_it = keys;
1231 0 : for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1232 0 : if (it->impl()) {
1233 0 : *keys_it++ = it->impl();
1234 : }
1235 : }
1236 0 : *keys_it++ = 0;
1237 :
1238 : gpgme_error_t op_err;
1239 0 : d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
1240 0 : delete[] keys;
1241 0 : Error error(d->lasterr);
1242 0 : if (error) {
1243 0 : return error;
1244 : }
1245 0 : return Error(d->lasterr = op_err);
1246 : }
1247 :
1248 0 : VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
1249 : {
1250 0 : d->lastop = Private::MountVFS;
1251 : gpgme_error_t op_err;
1252 0 : d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
1253 0 : return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
1254 : }
1255 :
1256 11 : Error Context::cancelPendingOperation()
1257 : {
1258 11 : return Error(gpgme_cancel_async(d->ctx));
1259 : }
1260 :
1261 0 : bool Context::poll()
1262 : {
1263 0 : gpgme_error_t e = GPG_ERR_NO_ERROR;
1264 0 : const bool finished = gpgme_wait(d->ctx, &e, 0);
1265 0 : if (finished) {
1266 0 : d->lasterr = e;
1267 : }
1268 0 : return finished;
1269 : }
1270 :
1271 0 : Error Context::wait()
1272 : {
1273 0 : gpgme_error_t e = GPG_ERR_NO_ERROR;
1274 0 : gpgme_wait(d->ctx, &e, 1);
1275 0 : return Error(d->lasterr = e);
1276 : }
1277 :
1278 22 : Error Context::lastError() const
1279 : {
1280 22 : return Error(d->lasterr);
1281 : }
1282 :
1283 0 : Context::PinentryMode Context::pinentryMode() const
1284 : {
1285 0 : switch (gpgme_get_pinentry_mode (d->ctx)) {
1286 : case GPGME_PINENTRY_MODE_ASK:
1287 0 : return PinentryAsk;
1288 : case GPGME_PINENTRY_MODE_CANCEL:
1289 0 : return PinentryCancel;
1290 : case GPGME_PINENTRY_MODE_ERROR:
1291 0 : return PinentryError;
1292 : case GPGME_PINENTRY_MODE_LOOPBACK:
1293 0 : return PinentryLoopback;
1294 : case GPGME_PINENTRY_MODE_DEFAULT:
1295 : default:
1296 0 : return PinentryDefault;
1297 : }
1298 : }
1299 :
1300 9 : Error Context::setPinentryMode(PinentryMode which)
1301 : {
1302 : gpgme_pinentry_mode_t mode;
1303 9 : switch (which) {
1304 : case PinentryAsk:
1305 0 : mode = GPGME_PINENTRY_MODE_ASK;
1306 0 : break;
1307 : case PinentryCancel:
1308 0 : mode = GPGME_PINENTRY_MODE_CANCEL;
1309 0 : break;
1310 : case PinentryError:
1311 0 : mode = GPGME_PINENTRY_MODE_ERROR;
1312 0 : break;
1313 : case PinentryLoopback:
1314 9 : mode = GPGME_PINENTRY_MODE_LOOPBACK;
1315 9 : break;
1316 : case PinentryDefault:
1317 : default:
1318 0 : mode = GPGME_PINENTRY_MODE_DEFAULT;
1319 : }
1320 9 : return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
1321 : }
1322 :
1323 : // Engine Spawn stuff
1324 0 : Error Context::spawn(const char *file, const char *argv[],
1325 : Data &input, Data &output, Data &err,
1326 : SpawnFlags flags)
1327 : {
1328 : return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
1329 0 : input.impl() ? input.impl()->data : nullptr,
1330 0 : output.impl() ? output.impl()->data : nullptr,
1331 0 : err.impl() ? err.impl()->data : nullptr,
1332 0 : static_cast<int>(flags)));
1333 : }
1334 :
1335 0 : Error Context::spawnAsync(const char *file, const char *argv[],
1336 : Data &input, Data &output, Data &err,
1337 : SpawnFlags flags)
1338 : {
1339 : return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
1340 0 : input.impl() ? input.impl()->data : nullptr,
1341 0 : output.impl() ? output.impl()->data : nullptr,
1342 0 : err.impl() ? err.impl()->data : nullptr,
1343 0 : static_cast<int>(flags)));
1344 : }
1345 :
1346 0 : std::ostream &operator<<(std::ostream &os, Protocol proto)
1347 : {
1348 0 : os << "GpgME::Protocol(";
1349 0 : switch (proto) {
1350 : case OpenPGP:
1351 0 : os << "OpenPGP";
1352 0 : break;
1353 : case CMS:
1354 0 : os << "CMS";
1355 0 : break;
1356 : default:
1357 : case UnknownProtocol:
1358 0 : os << "UnknownProtocol";
1359 0 : break;
1360 : }
1361 0 : return os << ')';
1362 : }
1363 :
1364 0 : std::ostream &operator<<(std::ostream &os, Engine eng)
1365 : {
1366 0 : os << "GpgME::Engine(";
1367 0 : switch (eng) {
1368 : case GpgEngine:
1369 0 : os << "GpgEngine";
1370 0 : break;
1371 : case GpgSMEngine:
1372 0 : os << "GpgSMEngine";
1373 0 : break;
1374 : case GpgConfEngine:
1375 0 : os << "GpgConfEngine";
1376 0 : break;
1377 : case AssuanEngine:
1378 0 : os << "AssuanEngine";
1379 0 : break;
1380 : case SpawnEngine:
1381 0 : os << "SpawnEngine";
1382 0 : break;
1383 : default:
1384 : case UnknownEngine:
1385 0 : os << "UnknownEngine";
1386 0 : break;
1387 : }
1388 0 : return os << ')';
1389 : }
1390 :
1391 0 : std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
1392 : {
1393 0 : os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
1394 0 : switch (incl) {
1395 : case Context::DefaultCertificates:
1396 0 : os << "(DefaultCertificates)";
1397 0 : break;
1398 : case Context::AllCertificatesExceptRoot:
1399 0 : os << "(AllCertificatesExceptRoot)";
1400 0 : break;
1401 : case Context::AllCertificates:
1402 0 : os << "(AllCertificates)";
1403 0 : break;
1404 : case Context::NoCertificates:
1405 0 : os << "(NoCertificates)";
1406 0 : break;
1407 : case Context::OnlySenderCertificate:
1408 0 : os << "(OnlySenderCertificate)";
1409 0 : break;
1410 : }
1411 0 : return os << ')';
1412 : }
1413 :
1414 0 : std::ostream &operator<<(std::ostream &os, KeyListMode mode)
1415 : {
1416 0 : os << "GpgME::KeyListMode(";
1417 : #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
1418 0 : CHECK(Local);
1419 0 : CHECK(Extern);
1420 0 : CHECK(Signatures);
1421 0 : CHECK(Validate);
1422 0 : CHECK(Ephemeral);
1423 0 : CHECK(WithTofu);
1424 : #undef CHECK
1425 0 : return os << ')';
1426 : }
1427 :
1428 0 : std::ostream &operator<<(std::ostream &os, SignatureMode mode)
1429 : {
1430 0 : os << "GpgME::SignatureMode(";
1431 0 : switch (mode) {
1432 : #define CHECK( x ) case x: os << #x; break
1433 0 : CHECK(NormalSignatureMode);
1434 0 : CHECK(Detached);
1435 0 : CHECK(Clearsigned);
1436 : #undef CHECK
1437 : default:
1438 0 : os << "???" "(" << static_cast<int>(mode) << ')';
1439 0 : break;
1440 : }
1441 0 : return os << ')';
1442 : }
1443 :
1444 0 : std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
1445 : {
1446 0 : os << "GpgME::Context::EncryptionFlags(";
1447 : #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1448 0 : CHECK(AlwaysTrust);
1449 0 : CHECK(NoEncryptTo);
1450 0 : CHECK(Prepare);
1451 0 : CHECK(ExpectSign);
1452 0 : CHECK(NoCompress);
1453 0 : CHECK(Symmetric);
1454 : #undef CHECK
1455 0 : return os << ')';
1456 : }
1457 :
1458 0 : std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
1459 : {
1460 0 : os << "GpgME::Context::AuditLogFlags(";
1461 : #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1462 0 : CHECK(HtmlAuditLog);
1463 0 : CHECK(AuditLogWithHelp);
1464 : #undef CHECK
1465 0 : return os << ')';
1466 : }
1467 :
1468 : } // namespace GpgME
1469 :
1470 0 : GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
1471 : {
1472 0 : return Error(gpgme_set_locale(0, cat, val));
1473 : }
1474 :
1475 0 : GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
1476 : {
1477 0 : gpgme_engine_info_t ei = 0;
1478 0 : if (gpgme_get_engine_info(&ei)) {
1479 0 : return EngineInfo();
1480 : }
1481 :
1482 0 : const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1483 :
1484 0 : for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1485 0 : if (i->protocol == p) {
1486 0 : return EngineInfo(i);
1487 : }
1488 : }
1489 :
1490 0 : return EngineInfo();
1491 : }
1492 :
1493 1 : const char *GpgME::dirInfo(const char *what)
1494 : {
1495 1 : return gpgme_get_dirinfo(what);
1496 : }
1497 :
1498 6 : GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
1499 : {
1500 6 : const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1501 :
1502 6 : return Error(gpgme_engine_check_version(p));
1503 : }
1504 :
1505 : static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
1506 :
1507 6 : static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
1508 : {
1509 6 : switch (engine) {
1510 6 : case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP;
1511 0 : case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
1512 : case GpgME::GpgConfEngine:
1513 0 : return GPGME_PROTOCOL_GPGCONF;
1514 : case GpgME::AssuanEngine:
1515 0 : return GPGME_PROTOCOL_ASSUAN;
1516 : case GpgME::G13Engine:
1517 0 : return GPGME_PROTOCOL_G13;
1518 : case GpgME::SpawnEngine:
1519 0 : return GPGME_PROTOCOL_SPAWN;
1520 : case GpgME::UnknownEngine:
1521 : ;
1522 : }
1523 0 : return UNKNOWN_PROTOCOL;
1524 : }
1525 :
1526 6 : GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
1527 : {
1528 6 : gpgme_engine_info_t ei = 0;
1529 6 : if (gpgme_get_engine_info(&ei)) {
1530 0 : return EngineInfo();
1531 : }
1532 :
1533 6 : const gpgme_protocol_t p = engine2protocol(engine);
1534 :
1535 6 : for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1536 6 : if (i->protocol == p) {
1537 6 : return EngineInfo(i);
1538 : }
1539 : }
1540 :
1541 0 : return EngineInfo();
1542 : }
1543 :
1544 0 : GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
1545 : {
1546 0 : const gpgme_protocol_t p = engine2protocol(engine);
1547 :
1548 0 : return Error(gpgme_engine_check_version(p));
1549 : }
1550 :
1551 : static const unsigned long supported_features = 0
1552 : | GpgME::ValidatingKeylistModeFeature
1553 : | GpgME::CancelOperationFeature
1554 : | GpgME::WrongKeyUsageFeature
1555 : | GpgME::DefaultCertificateInclusionFeature
1556 : | GpgME::GetSetEngineInfoFeature
1557 : | GpgME::ClearAddGetSignatureNotationsFeature
1558 : | GpgME::SetDataFileNameFeeature
1559 : | GpgME::SignatureNotationsKeylistModeFeature
1560 : | GpgME::KeySignatureNotationsFeature
1561 : | GpgME::KeyIsQualifiedFeature
1562 : | GpgME::SignatureNotationsCriticalFlagFeature
1563 : | GpgME::SignatureNotationsFlagsFeature
1564 : | GpgME::SignatureNotationsHumanReadableFlagFeature
1565 : | GpgME::SubkeyIsQualifiedFeature
1566 : | GpgME::EngineInfoHomeDirFeature
1567 : | GpgME::DecryptionResultFileNameFeature
1568 : | GpgME::DecryptionResultRecipientsFeature
1569 : | GpgME::VerificationResultFileNameFeature
1570 : | GpgME::SignaturePkaFieldsFeature
1571 : | GpgME::SignatureAlgorithmFieldsFeature
1572 : | GpgME::FdPointerFeature
1573 : | GpgME::AuditLogFeature
1574 : | GpgME::GpgConfEngineFeature
1575 : | GpgME::CancelOperationAsyncFeature
1576 : | GpgME::NoEncryptToEncryptionFlagFeature
1577 : | GpgME::CardKeyFeature
1578 : | GpgME::AssuanEngineFeature
1579 : | GpgME::EphemeralKeylistModeFeature
1580 : | GpgME::ImportFromKeyserverFeature
1581 : | GpgME::G13VFSFeature
1582 : | GpgME::PasswdFeature
1583 : ;
1584 :
1585 : static const unsigned long supported_features2 = 0
1586 : | GpgME::BinaryAndFineGrainedIdentify
1587 : ;
1588 :
1589 0 : bool GpgME::hasFeature(unsigned long features)
1590 : {
1591 0 : return features == (features & supported_features);
1592 : }
1593 :
1594 0 : bool GpgME::hasFeature(unsigned long features, unsigned long features2)
1595 : {
1596 0 : return features == (features & supported_features)
1597 0 : && features2 == (features2 & supported_features2)
1598 : ;
1599 18 : }
|