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