1 #![allow(trivial_numeric_casts)]
2 use std::{
3     ffi::CStr,
4     fmt,
5     marker::PhantomData,
6     result,
7     str::Utf8Error,
8     time::{Duration, SystemTime, UNIX_EPOCH},
9 };
10 
11 use ffi::{self, require_gpgme_ver};
12 use libc;
13 
14 use crate::{
15     error::return_err, notation::SignatureNotations, Context, Error, HashAlgorithm, ImportFlags,
16     KeyAlgorithm, NonNull, OpResult, Result, SignMode, SignatureSummary, Validity,
17 };
18 
19 macro_rules! impl_result {
20     ($(#[$Attr:meta])* $Name:ident : $T:ty = $Constructor:expr) => {
21         $(#[$Attr])*
22         pub struct $Name(NonNull<$T>);
23 
24         unsafe impl Send for $Name {}
25         unsafe impl Sync for $Name {}
26 
27         impl Drop for $Name {
28             #[inline]
29             fn drop(&mut self) {
30                 unsafe {
31                     ffi::gpgme_result_unref(self.as_raw() as *mut libc::c_void);
32                 }
33             }
34         }
35 
36         impl Clone for $Name {
37             #[inline]
38             fn clone(&self) -> Self {
39                 unsafe {
40                     ffi::gpgme_result_ref(self.as_raw() as *mut libc::c_void);
41                     Self::from_raw(self.as_raw())
42                 }
43             }
44         }
45 
46         unsafe impl OpResult for $Name {
47             fn from_context(ctx: &Context) -> Option<Self> {
48                 unsafe {
49                     $Constructor(ctx.as_raw()).as_mut().map(|r| {
50                         ffi::gpgme_result_ref(r as *mut _ as *mut libc::c_void);
51                         Self::from_raw(r)
52                     })
53                 }
54             }
55         }
56 
57         impl $Name {
58             impl_wrapper!($T);
59         }
60     };
61 }
62 
63 macro_rules! impl_subresult {
64     ($(#[$Attr:meta])* $Name:ident : $T:ty, $IterName:ident, $Owner:ty) => {
65         $(#[$Attr])*
66         #[derive(Copy, Clone)]
67         pub struct $Name<'result>(NonNull<$T>, PhantomData<&'result $Owner>);
68 
69         unsafe impl Send for $Name<'_> {}
70         unsafe impl Sync for $Name<'_> {}
71 
72         impl $Name<'_> {
73             impl_wrapper!($T, PhantomData);
74         }
75 
76         impl_list_iterator!(pub struct $IterName($Name: $T));
77     };
78 }
79 
80 impl_subresult! {
81     /// Upstream documentation:
82     /// [`gpgme_invalid_key_t`](https://www.gnupg.org/documentation/manuals/gpgme/Crypto-Operations.html#index-gpgme_005finvalid_005fkey_005ft)
83     InvalidKey: ffi::gpgme_invalid_key_t, InvalidKeys, ()
84 }
85 
86 impl<'a> InvalidKey<'a> {
87     #[inline]
fingerprint(&self) -> result::Result<&'a str, Option<Utf8Error>>88     pub fn fingerprint(&self) -> result::Result<&'a str, Option<Utf8Error>> {
89         self.fingerprint_raw()
90             .map_or(Err(None), |s| s.to_str().map_err(Some))
91     }
92 
93     #[inline]
fingerprint_raw(&self) -> Option<&'a CStr>94     pub fn fingerprint_raw(&self) -> Option<&'a CStr> {
95         unsafe { (*self.as_raw()).fpr.as_ref().map(|s| CStr::from_ptr(s)) }
96     }
97 
98     #[inline]
reason(&self) -> Option<Error>99     pub fn reason(&self) -> Option<Error> {
100         unsafe {
101             match Error::new((*self.as_raw()).reason) {
102                 Error::NO_ERROR => None,
103                 e => Some(e),
104             }
105         }
106     }
107 }
108 
109 impl fmt::Debug for InvalidKey<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result110     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111         f.debug_struct("InvalidKey")
112             .field("raw", &self.as_raw())
113             .field("fingerprint", &self.fingerprint_raw())
114             .field("reason", &self.reason())
115             .finish()
116     }
117 }
118 
119 impl_result! {
120     /// Upstream documentation:
121     /// [`gpgme_keylist_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Listing-Keys.html#index-gpgme_005fkeylist_005fresult_005ft)
122     KeyListResult: ffi::gpgme_keylist_result_t = ffi::gpgme_op_keylist_result
123 }
124 impl KeyListResult {
is_truncated(&self) -> bool125     pub fn is_truncated(&self) -> bool {
126         unsafe { (*self.as_raw()).truncated() }
127     }
128 }
129 
130 impl fmt::Debug for KeyListResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result131     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132         f.debug_struct("KeyListResult")
133             .field("raw", &self.as_raw())
134             .field("truncated", &self.is_truncated())
135             .finish()
136     }
137 }
138 
139 impl_result! {
140     /// Upstream documentation:
141     /// [`gpgme_genkey_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Generating-Keys.html#index-gpgme_005fgenkey_005fresult_005ft)
142     KeyGenerationResult: ffi::gpgme_genkey_result_t = ffi::gpgme_op_genkey_result
143 }
144 impl KeyGenerationResult {
145     #[inline]
has_primary_key(&self) -> bool146     pub fn has_primary_key(&self) -> bool {
147         unsafe { (*self.as_raw()).primary() }
148     }
149 
150     #[inline]
has_sub_key(&self) -> bool151     pub fn has_sub_key(&self) -> bool {
152         unsafe { (*self.as_raw()).sub() }
153     }
154 
155     #[inline]
has_uid(&self) -> bool156     pub fn has_uid(&self) -> bool {
157         unsafe { (*self.as_raw()).uid() }
158     }
159 
160     #[inline]
fingerprint(&self) -> result::Result<&str, Option<Utf8Error>>161     pub fn fingerprint(&self) -> result::Result<&str, Option<Utf8Error>> {
162         self.fingerprint_raw()
163             .map_or(Err(None), |s| s.to_str().map_err(Some))
164     }
165 
166     #[inline]
fingerprint_raw(&self) -> Option<&CStr>167     pub fn fingerprint_raw(&self) -> Option<&CStr> {
168         unsafe { (*self.as_raw()).fpr.as_ref().map(|s| CStr::from_ptr(s)) }
169     }
170 }
171 
172 impl fmt::Debug for KeyGenerationResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result173     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174         f.debug_struct("KeyGenerationResult")
175             .field("raw", &self.as_raw())
176             .field("fingerprint", &self.fingerprint_raw())
177             .finish()
178     }
179 }
180 
181 impl_result! {
182     /// Upstream documentation:
183     /// [`gpgme_import_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Importing-Keys.html#index-gpgme_005fimport_005fresult_005ft)
184     ImportResult: ffi::gpgme_import_result_t = ffi::gpgme_op_import_result
185 }
186 impl ImportResult {
187     #[inline]
considered(&self) -> u32188     pub fn considered(&self) -> u32 {
189         unsafe { (*self.as_raw()).considered as u32 }
190     }
191 
192     #[inline]
without_user_id(&self) -> u32193     pub fn without_user_id(&self) -> u32 {
194         unsafe { (*self.as_raw()).no_user_id as u32 }
195     }
196 
197     #[inline]
imported(&self) -> u32198     pub fn imported(&self) -> u32 {
199         unsafe { (*self.as_raw()).imported as u32 }
200     }
201 
202     #[inline]
imported_rsa(&self) -> u32203     pub fn imported_rsa(&self) -> u32 {
204         unsafe { (*self.as_raw()).imported_rsa as u32 }
205     }
206 
207     #[inline]
unchanged(&self) -> u32208     pub fn unchanged(&self) -> u32 {
209         unsafe { (*self.as_raw()).unchanged as u32 }
210     }
211 
212     #[inline]
new_user_ids(&self) -> u32213     pub fn new_user_ids(&self) -> u32 {
214         unsafe { (*self.as_raw()).new_user_ids as u32 }
215     }
216 
217     #[inline]
new_subkeys(&self) -> u32218     pub fn new_subkeys(&self) -> u32 {
219         unsafe { (*self.as_raw()).new_sub_keys as u32 }
220     }
221 
222     #[inline]
new_signatures(&self) -> u32223     pub fn new_signatures(&self) -> u32 {
224         unsafe { (*self.as_raw()).new_signatures as u32 }
225     }
226 
227     #[inline]
new_revocations(&self) -> u32228     pub fn new_revocations(&self) -> u32 {
229         unsafe { (*self.as_raw()).new_revocations as u32 }
230     }
231 
232     #[inline]
secret_considered(&self) -> u32233     pub fn secret_considered(&self) -> u32 {
234         unsafe { (*self.as_raw()).secret_read as u32 }
235     }
236 
237     #[inline]
secret_imported(&self) -> u32238     pub fn secret_imported(&self) -> u32 {
239         unsafe { (*self.as_raw()).secret_imported as u32 }
240     }
241 
242     #[inline]
secret_unchanged(&self) -> u32243     pub fn secret_unchanged(&self) -> u32 {
244         unsafe { (*self.as_raw()).secret_unchanged as u32 }
245     }
246 
247     #[inline]
not_imported(&self) -> u32248     pub fn not_imported(&self) -> u32 {
249         unsafe { (*self.as_raw()).not_imported as u32 }
250     }
251 
252     #[inline]
skipped_v3_keys(&self) -> u32253     pub fn skipped_v3_keys(&self) -> u32 {
254         require_gpgme_ver! {
255             (1, 11) => {
256                 unsafe { (*self.as_raw()).skipped_v3_keys as u32 }
257             } else {
258                 0
259             }
260         }
261     }
262 
263     #[inline]
imports(&self) -> Imports<'_>264     pub fn imports(&self) -> Imports<'_> {
265         unsafe { Imports::from_list((*self.as_raw()).imports) }
266     }
267 }
268 
269 impl fmt::Debug for ImportResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result270     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271         f.debug_struct("ImportResult")
272             .field("raw", &self.as_raw())
273             .field("without_user_id", &self.without_user_id())
274             .field("new_user_ids", &self.new_user_ids())
275             .field("new_subkeys", &self.new_subkeys())
276             .field("new_signatures", &self.new_signatures())
277             .field("new_revocations", &self.new_revocations())
278             .field("considered", &self.considered())
279             .field("imported", &self.imported())
280             .field("unchanged", &self.unchanged())
281             .field("secret_considered", &self.secret_considered())
282             .field("secret_imported", &self.secret_imported())
283             .field("secret_unchanged", &self.secret_unchanged())
284             .field("not_imported", &self.not_imported())
285             .field("imports", &self.imports())
286             .finish()
287     }
288 }
289 
290 impl_subresult! {
291     /// Upstream documentation:
292     /// [`gpgme_import_status_t`](https://www.gnupg.org/documentation/manuals/gpgme/Importing-Keys.html#index-gpgme_005fimport_005fstatus_005ft)
293     Import: ffi::gpgme_import_status_t, Imports, ImportResult
294 }
295 impl<'result> Import<'result> {
296     #[inline]
fingerprint(&self) -> result::Result<&'result str, Option<Utf8Error>>297     pub fn fingerprint(&self) -> result::Result<&'result str, Option<Utf8Error>> {
298         self.fingerprint_raw()
299             .map_or(Err(None), |s| s.to_str().map_err(Some))
300     }
301 
302     #[inline]
fingerprint_raw(&self) -> Option<&'result CStr>303     pub fn fingerprint_raw(&self) -> Option<&'result CStr> {
304         unsafe { (*self.as_raw()).fpr.as_ref().map(|s| CStr::from_ptr(s)) }
305     }
306 
307     #[inline]
result(&self) -> Result<()>308     pub fn result(&self) -> Result<()> {
309         unsafe {
310             return_err!((*self.as_raw()).result);
311             Ok(())
312         }
313     }
314 
315     #[inline]
status(&self) -> ImportFlags316     pub fn status(&self) -> ImportFlags {
317         unsafe { ImportFlags::from_bits_truncate((*self.as_raw()).status) }
318     }
319 }
320 
321 impl fmt::Debug for Import<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result322     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323         f.debug_struct("Import")
324             .field("raw", &self.as_raw())
325             .field("fingerprint", &self.fingerprint_raw())
326             .field("result", &self.result())
327             .field("status", &self.status())
328             .finish()
329     }
330 }
331 
332 impl_result! {
333     /// Upstream documentation:
334     /// [`gpgme_encrypt_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Encrypting-a-Plaintext.html#index-gpgme_005fencrypt_005fresult_005ft)
335     EncryptionResult: ffi::gpgme_encrypt_result_t = ffi::gpgme_op_encrypt_result
336 }
337 impl EncryptionResult {
338     #[inline]
invalid_recipients(&self) -> InvalidKeys<'_>339     pub fn invalid_recipients(&self) -> InvalidKeys<'_> {
340         unsafe { InvalidKeys::from_list((*self.as_raw()).invalid_recipients) }
341     }
342 }
343 
344 impl fmt::Debug for EncryptionResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result345     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346         f.debug_struct("EncryptionResult")
347             .field("raw", &self.as_raw())
348             .field("invalid_recipients", &self.invalid_recipients())
349             .finish()
350     }
351 }
352 
353 impl_result! {
354     /// Upstream documentation:
355     /// [`gpgme_decrypt_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Decrypt.html#index-gpgme_005fdecrypt_005fresult_005ft)
356     DecryptionResult: ffi::gpgme_decrypt_result_t = ffi::gpgme_op_decrypt_result
357 }
358 impl DecryptionResult {
359     #[inline]
unsupported_algorithm(&self) -> result::Result<&str, Option<Utf8Error>>360     pub fn unsupported_algorithm(&self) -> result::Result<&str, Option<Utf8Error>> {
361         self.unsupported_algorithm_raw()
362             .map_or(Err(None), |s| s.to_str().map_err(Some))
363     }
364 
365     #[inline]
unsupported_algorithm_raw(&self) -> Option<&CStr>366     pub fn unsupported_algorithm_raw(&self) -> Option<&CStr> {
367         unsafe {
368             (*self.as_raw())
369                 .unsupported_algorithm
370                 .as_ref()
371                 .map(|s| CStr::from_ptr(s))
372         }
373     }
374 
375     #[inline]
is_wrong_key_usage(&self) -> bool376     pub fn is_wrong_key_usage(&self) -> bool {
377         unsafe { (*self.as_raw()).wrong_key_usage() }
378     }
379 
380     #[inline]
is_de_vs(&self) -> bool381     pub fn is_de_vs(&self) -> bool {
382         require_gpgme_ver! {
383             (1, 10) => {
384                 unsafe { (*self.as_raw()).is_de_vs() }
385             } else {
386                 false
387             }
388         }
389     }
390 
391     #[inline]
is_mime(&self) -> bool392     pub fn is_mime(&self) -> bool {
393         require_gpgme_ver! {
394             (1, 11) => {
395                 unsafe { (*self.as_raw()).is_mime() }
396             } else {
397                 false
398             }
399         }
400     }
401 
402     require_gpgme_ver! {
403         (1, 12) => {
404             #[inline]
405             pub fn is_legacy_cipher_no_mdc(&self) -> bool {
406                 unsafe { (*self.as_raw()).legacy_cipher_nomdc() }
407             }
408         }
409     }
410 
411     #[inline]
filename(&self) -> result::Result<&str, Option<Utf8Error>>412     pub fn filename(&self) -> result::Result<&str, Option<Utf8Error>> {
413         self.filename_raw()
414             .map_or(Err(None), |s| s.to_str().map_err(Some))
415     }
416 
417     #[inline]
filename_raw(&self) -> Option<&CStr>418     pub fn filename_raw(&self) -> Option<&CStr> {
419         unsafe {
420             (*self.as_raw())
421                 .file_name
422                 .as_ref()
423                 .map(|s| CStr::from_ptr(s))
424         }
425     }
426 
427     #[inline]
symmetric_key_algorithm(&self) -> result::Result<&str, Option<Utf8Error>>428     pub fn symmetric_key_algorithm(&self) -> result::Result<&str, Option<Utf8Error>> {
429         self.symmetric_key_algorithm_raw()
430             .map_or(Err(None), |s| s.to_str().map_err(Some))
431     }
432 
433     #[inline]
symmetric_key_algorithm_raw(&self) -> Option<&CStr>434     pub fn symmetric_key_algorithm_raw(&self) -> Option<&CStr> {
435         require_gpgme_ver! {
436             (1, 11) => {
437                 unsafe {
438                     (*self.as_raw()).symkey_algo.as_ref().map(|s| CStr::from_ptr(s))
439                 }
440             } else {
441                 None
442             }
443         }
444     }
445 
446     #[inline]
recipients(&self) -> Recipients<'_>447     pub fn recipients(&self) -> Recipients<'_> {
448         unsafe { Recipients::from_list((*self.as_raw()).recipients) }
449     }
450 }
451 
452 impl fmt::Debug for DecryptionResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result453     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
454         f.debug_struct("DecryptionResult")
455             .field("raw", &self.as_raw())
456             .field("unsupported_algorithm", &self.unsupported_algorithm_raw())
457             .field("wrong_key_usage", &self.is_wrong_key_usage())
458             .field("filename", &self.filename_raw())
459             .field("recipients", &self.recipients())
460             .finish()
461     }
462 }
463 
464 impl_subresult! {
465     /// Upstream documentation:
466     /// [`gpgme_recipient_t`](https://www.gnupg.org/documentation/manuals/gpgme/Decrypt.html#index-gpgme_005frecipient_005ft)
467     Recipient: ffi::gpgme_recipient_t,
468     Recipients,
469     DecryptionResult
470 }
471 impl<'result> Recipient<'result> {
472     #[inline]
key_id(&self) -> result::Result<&'result str, Option<Utf8Error>>473     pub fn key_id(&self) -> result::Result<&'result str, Option<Utf8Error>> {
474         self.key_id_raw()
475             .map_or(Err(None), |s| s.to_str().map_err(Some))
476     }
477 
478     #[inline]
key_id_raw(&self) -> Option<&'result CStr>479     pub fn key_id_raw(&self) -> Option<&'result CStr> {
480         unsafe { (*self.as_raw()).keyid.as_ref().map(|s| CStr::from_ptr(s)) }
481     }
482 
483     #[inline]
algorithm(&self) -> KeyAlgorithm484     pub fn algorithm(&self) -> KeyAlgorithm {
485         unsafe { KeyAlgorithm::from_raw((*self.as_raw()).pubkey_algo) }
486     }
487 
488     #[inline]
status(&self) -> Result<()>489     pub fn status(&self) -> Result<()> {
490         unsafe {
491             return_err!((*self.as_raw()).status);
492             Ok(())
493         }
494     }
495 }
496 
497 impl fmt::Debug for Recipient<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result498     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
499         f.debug_struct("Recipient")
500             .field("raw", &self.as_raw())
501             .field("key_id", &self.key_id_raw())
502             .field("algorithm", &self.algorithm())
503             .field("status", &self.status())
504             .finish()
505     }
506 }
507 
508 impl_result! {
509     /// Upstream documentation:
510     /// [`gpgme_sign_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Creating-a-Signature.html#index-gpgme_005fsign_005fresult_005ft)
511     SigningResult: ffi::gpgme_sign_result_t = ffi::gpgme_op_sign_result
512 }
513 impl SigningResult {
514     #[inline]
invalid_signers(&self) -> InvalidKeys<'_>515     pub fn invalid_signers(&self) -> InvalidKeys<'_> {
516         unsafe { InvalidKeys::from_list((*self.as_raw()).invalid_signers) }
517     }
518 
519     #[inline]
new_signatures(&self) -> NewSignatures<'_>520     pub fn new_signatures(&self) -> NewSignatures<'_> {
521         unsafe { NewSignatures::from_list((*self.as_raw()).signatures) }
522     }
523 }
524 
525 impl fmt::Debug for SigningResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result526     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527         f.debug_struct("SigningResult")
528             .field("raw", &self.as_raw())
529             .field("invalid_signers", &self.invalid_signers())
530             .field("new_signatures", &self.new_signatures())
531             .finish()
532     }
533 }
534 
535 impl_subresult! {
536     /// Upstream documentation:
537     /// [`gpgme_new_signature_t`](https://www.gnupg.org/documentation/manuals/gpgme/Creating-a-Signature.html#index-gpgme_005fnew_005fsignature_005ft)
538     NewSignature: ffi::gpgme_new_signature_t,
539     NewSignatures,
540     SigningResult
541 }
542 impl<'result> NewSignature<'result> {
543     #[inline]
fingerprint(&self) -> result::Result<&'result str, Option<Utf8Error>>544     pub fn fingerprint(&self) -> result::Result<&'result str, Option<Utf8Error>> {
545         self.fingerprint_raw()
546             .map_or(Err(None), |s| s.to_str().map_err(Some))
547     }
548 
549     #[inline]
fingerprint_raw(&self) -> Option<&'result CStr>550     pub fn fingerprint_raw(&self) -> Option<&'result CStr> {
551         unsafe { (*self.as_raw()).fpr.as_ref().map(|s| CStr::from_ptr(s)) }
552     }
553 
554     #[inline]
creation_time(&self) -> SystemTime555     pub fn creation_time(&self) -> SystemTime {
556         let timestamp = unsafe { (*self.as_raw()).timestamp };
557         UNIX_EPOCH + Duration::from_secs(timestamp as u64)
558     }
559 
560     #[inline]
mode(&self) -> SignMode561     pub fn mode(&self) -> SignMode {
562         unsafe { SignMode::from_raw((*self.as_raw()).typ) }
563     }
564 
565     #[inline]
key_algorithm(&self) -> KeyAlgorithm566     pub fn key_algorithm(&self) -> KeyAlgorithm {
567         unsafe { KeyAlgorithm::from_raw((*self.as_raw()).pubkey_algo) }
568     }
569 
570     #[inline]
hash_algorithm(&self) -> HashAlgorithm571     pub fn hash_algorithm(&self) -> HashAlgorithm {
572         unsafe { HashAlgorithm::from_raw((*self.as_raw()).hash_algo) }
573     }
574 
575     #[inline]
signature_class(&self) -> u32576     pub fn signature_class(&self) -> u32 {
577         unsafe { (*self.as_raw()).sig_class.into() }
578     }
579 }
580 
581 impl fmt::Debug for NewSignature<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result582     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583         f.debug_struct("NewSignature")
584             .field("raw", &self.as_raw())
585             .field("fingerprint", &self.fingerprint_raw())
586             .field("creation_time", &self.creation_time())
587             .field("mode", &self.mode())
588             .field("key_algorithm", &self.key_algorithm())
589             .field("hash_algorithm", &self.hash_algorithm())
590             .field("class", &self.signature_class())
591             .finish()
592     }
593 }
594 
595 impl_result! {
596     /// Upstream documentation:
597     /// [`gpgme_verify_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Verify.html#index-gpgme_005fverify_005fresult_005ft)
598     VerificationResult: ffi::gpgme_verify_result_t = ffi::gpgme_op_verify_result
599 }
600 impl VerificationResult {
601     #[inline]
is_mime(&self) -> bool602     pub fn is_mime(&self) -> bool {
603         require_gpgme_ver! {
604             (1, 11) => {
605                 unsafe { (*self.as_raw()).is_mime() }
606             } else {
607                 false
608             }
609         }
610     }
611 
612     #[inline]
filename(&self) -> result::Result<&str, Option<Utf8Error>>613     pub fn filename(&self) -> result::Result<&str, Option<Utf8Error>> {
614         self.filename_raw()
615             .map_or(Err(None), |s| s.to_str().map_err(Some))
616     }
617 
618     #[inline]
filename_raw(&self) -> Option<&CStr>619     pub fn filename_raw(&self) -> Option<&CStr> {
620         unsafe {
621             (*self.as_raw())
622                 .file_name
623                 .as_ref()
624                 .map(|s| CStr::from_ptr(s))
625         }
626     }
627 
628     #[inline]
signatures(&self) -> Signatures<'_>629     pub fn signatures(&self) -> Signatures<'_> {
630         unsafe { Signatures::from_list((*self.as_raw()).signatures) }
631     }
632 }
633 
634 impl fmt::Debug for VerificationResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result635     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
636         f.debug_struct("VerificationResult")
637             .field("raw", &self.as_raw())
638             .field("filename", &self.filename_raw())
639             .field("signatures", &self.signatures())
640             .finish()
641     }
642 }
643 
644 ffi_enum_wrapper! {
645     /// Upstream documentation:
646     /// [`gpgme_signature_t`](https://www.gnupg.org/documentation/manuals/gpgme/Verify.html#index-gpgme_005fsignature_005ft)
647     pub enum PkaTrust: libc::c_uint {
648         Unknown = 0,
649         Bad = 1,
650         Okay = 2,
651     }
652 }
653 
654 impl_subresult! {
655     /// Upstream documentation:
656     /// [`gpgme_signature_t`](https://www.gnupg.org/documentation/manuals/gpgme/Verify.html#index-gpgme_005fsignature_005ft)
657     Signature: ffi::gpgme_signature_t,
658     Signatures,
659     VerificationResult
660 }
661 impl<'result> Signature<'result> {
662     #[inline]
summary(&self) -> SignatureSummary663     pub fn summary(&self) -> SignatureSummary {
664         unsafe { SignatureSummary::from_bits_truncate((*self.as_raw()).summary as u32) }
665     }
666 
667     #[inline]
fingerprint(&self) -> result::Result<&'result str, Option<Utf8Error>>668     pub fn fingerprint(&self) -> result::Result<&'result str, Option<Utf8Error>> {
669         self.fingerprint_raw()
670             .map_or(Err(None), |s| s.to_str().map_err(Some))
671     }
672 
673     #[inline]
fingerprint_raw(&self) -> Option<&'result CStr>674     pub fn fingerprint_raw(&self) -> Option<&'result CStr> {
675         unsafe { (*self.as_raw()).fpr.as_ref().map(|s| CStr::from_ptr(s)) }
676     }
677 
678     #[inline]
status(&self) -> Result<()>679     pub fn status(&self) -> Result<()> {
680         unsafe {
681             return_err!((*self.as_raw()).status);
682             Ok(())
683         }
684     }
685 
686     #[inline]
creation_time(&self) -> Option<SystemTime>687     pub fn creation_time(&self) -> Option<SystemTime> {
688         let timestamp = unsafe { (*self.as_raw()).timestamp };
689         if timestamp > 0 {
690             Some(UNIX_EPOCH + Duration::from_secs(timestamp.into()))
691         } else {
692             None
693         }
694     }
695 
696     #[inline]
expiration_time(&self) -> Option<SystemTime>697     pub fn expiration_time(&self) -> Option<SystemTime> {
698         let expires = unsafe { (*self.as_raw()).exp_timestamp };
699         if expires > 0 {
700             Some(UNIX_EPOCH + Duration::from_secs(expires.into()))
701         } else {
702             None
703         }
704     }
705 
706     #[inline]
never_expires(&self) -> bool707     pub fn never_expires(&self) -> bool {
708         self.expiration_time().is_none()
709     }
710 
711     #[inline]
is_wrong_key_usage(&self) -> bool712     pub fn is_wrong_key_usage(&self) -> bool {
713         unsafe { (*self.as_raw()).wrong_key_usage() }
714     }
715 
716     #[inline]
verified_by_chain(&self) -> bool717     pub fn verified_by_chain(&self) -> bool {
718         unsafe { (*self.as_raw()).chain_model() }
719     }
720 
721     #[inline]
is_de_vs(&self) -> bool722     pub fn is_de_vs(&self) -> bool {
723         require_gpgme_ver! {
724             (1, 10) => {
725                 unsafe { (*self.as_raw()).is_de_vs() }
726             } else {
727                 false
728             }
729         }
730     }
731 
732     #[inline]
pka_trust(&self) -> PkaTrust733     pub fn pka_trust(&self) -> PkaTrust {
734         unsafe { PkaTrust::from_raw((*self.as_raw()).pka_trust()) }
735     }
736 
737     #[inline]
pka_address(&self) -> result::Result<&'result str, Option<Utf8Error>>738     pub fn pka_address(&self) -> result::Result<&'result str, Option<Utf8Error>> {
739         self.pka_address_raw()
740             .map_or(Err(None), |s| s.to_str().map_err(Some))
741     }
742 
743     #[inline]
pka_address_raw(&self) -> Option<&'result CStr>744     pub fn pka_address_raw(&self) -> Option<&'result CStr> {
745         unsafe {
746             (*self.as_raw())
747                 .pka_address
748                 .as_ref()
749                 .map(|s| CStr::from_ptr(s))
750         }
751     }
752 
753     #[inline]
validity(&self) -> Validity754     pub fn validity(&self) -> Validity {
755         unsafe { Validity::from_raw((*self.as_raw()).validity) }
756     }
757 
758     #[inline]
nonvalidity_reason(&self) -> Option<Error>759     pub fn nonvalidity_reason(&self) -> Option<Error> {
760         unsafe {
761             match Error::new((*self.as_raw()).validity_reason) {
762                 Error::NO_ERROR => None,
763                 e => Some(e),
764             }
765         }
766     }
767 
768     #[inline]
key_algorithm(&self) -> KeyAlgorithm769     pub fn key_algorithm(&self) -> KeyAlgorithm {
770         unsafe { KeyAlgorithm::from_raw((*self.as_raw()).pubkey_algo) }
771     }
772 
773     #[inline]
hash_algorithm(&self) -> HashAlgorithm774     pub fn hash_algorithm(&self) -> HashAlgorithm {
775         unsafe { HashAlgorithm::from_raw((*self.as_raw()).hash_algo) }
776     }
777 
778     #[inline]
policy_url(&self) -> result::Result<&'result str, Option<Utf8Error>>779     pub fn policy_url(&self) -> result::Result<&'result str, Option<Utf8Error>> {
780         self.policy_url_raw()
781             .map_or(Err(None), |s| s.to_str().map_err(Some))
782     }
783 
784     #[inline]
policy_url_raw(&self) -> Option<&'result CStr>785     pub fn policy_url_raw(&self) -> Option<&'result CStr> {
786         unsafe {
787             let mut notation = (*self.as_raw()).notations;
788             while !notation.is_null() {
789                 if (*notation).name.is_null() {
790                     return (*notation).value.as_ref().map(|s| CStr::from_ptr(s));
791                 }
792                 notation = (*notation).next;
793             }
794             None
795         }
796     }
797 
798     #[inline]
notations(&self) -> SignatureNotations<'result>799     pub fn notations(&self) -> SignatureNotations<'result> {
800         unsafe { SignatureNotations::from_list((*self.as_raw()).notations) }
801     }
802 
803     #[inline]
key(&self) -> Option<crate::Key>804     pub fn key(&self) -> Option<crate::Key> {
805         require_gpgme_ver! {
806             (1, 7) => {
807                 unsafe {
808                     (*self.as_raw()).key.as_mut().map(|k| {
809                         ffi::gpgme_key_ref(k);
810                         crate::Key::from_raw(k)
811                     })
812                 }
813             } else {
814                 None
815             }
816         }
817     }
818 }
819 
820 impl fmt::Debug for Signature<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result821     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
822         f.debug_struct("Signature")
823             .field("raw", &self.as_raw())
824             .field("fingerprint", &self.fingerprint_raw())
825             .field("creation_time", &self.creation_time())
826             .field("expiration_time", &self.expiration_time())
827             .field("key_algorithm", &self.key_algorithm())
828             .field("hash_algorithm", &self.hash_algorithm())
829             .field("summary", &self.summary())
830             .field("status", &self.status())
831             .field("validity", &self.validity())
832             .field("nonvalidity_reason", &self.nonvalidity_reason())
833             .field("notations", &self.notations())
834             .finish()
835     }
836 }
837 
838 impl_result! {
839     /// Upstream documentation:
840     /// [`gpgme_query_swdb_result_t`](https://www.gnupg.org/documentation/manuals/gpgme/Checking-for-updates.html#index-gpgme_005fquery_005fswdb_005fresult_005ft)
841     QuerySwdbResult: ffi::gpgme_query_swdb_result_t = ffi::gpgme_op_query_swdb_result
842 }
843 impl QuerySwdbResult {
844     #[inline]
name(&self) -> result::Result<&str, Option<Utf8Error>>845     pub fn name(&self) -> result::Result<&str, Option<Utf8Error>> {
846         self.name_raw()
847             .map_or(Err(None), |s| s.to_str().map_err(Some))
848     }
849 
850     #[inline]
name_raw(&self) -> Option<&CStr>851     pub fn name_raw(&self) -> Option<&CStr> {
852         unsafe { (*self.as_raw()).name.as_ref().map(|s| CStr::from_ptr(s)) }
853     }
854 
855     #[inline]
installed_version(&self) -> result::Result<&str, Option<Utf8Error>>856     pub fn installed_version(&self) -> result::Result<&str, Option<Utf8Error>> {
857         self.installed_version_raw()
858             .map_or(Err(None), |s| s.to_str().map_err(Some))
859     }
860 
861     #[inline]
installed_version_raw(&self) -> Option<&CStr>862     pub fn installed_version_raw(&self) -> Option<&CStr> {
863         unsafe {
864             (*self.as_raw())
865                 .iversion
866                 .as_ref()
867                 .map(|s| CStr::from_ptr(s))
868         }
869     }
870 
871     #[inline]
latest_version(&self) -> result::Result<&str, Option<Utf8Error>>872     pub fn latest_version(&self) -> result::Result<&str, Option<Utf8Error>> {
873         self.latest_version_raw()
874             .map_or(Err(None), |s| s.to_str().map_err(Some))
875     }
876 
877     #[inline]
latest_version_raw(&self) -> Option<&CStr>878     pub fn latest_version_raw(&self) -> Option<&CStr> {
879         unsafe { (*self.as_raw()).version.as_ref().map(|s| CStr::from_ptr(s)) }
880     }
881 
882     #[inline]
creation_time(&self) -> Option<SystemTime>883     pub fn creation_time(&self) -> Option<SystemTime> {
884         let timestamp = unsafe { (*self.as_raw()).created };
885         if timestamp > 0 {
886             Some(UNIX_EPOCH + Duration::from_secs(timestamp.into()))
887         } else {
888             None
889         }
890     }
891 
892     #[inline]
retrieval_time(&self) -> Option<SystemTime>893     pub fn retrieval_time(&self) -> Option<SystemTime> {
894         let timestamp = unsafe { (*self.as_raw()).retrieved };
895         if timestamp > 0 {
896             Some(UNIX_EPOCH + Duration::from_secs(timestamp.into()))
897         } else {
898             None
899         }
900     }
901 
902     #[inline]
release_time(&self) -> Option<SystemTime>903     pub fn release_time(&self) -> Option<SystemTime> {
904         let timestamp = unsafe { (*self.as_raw()).reldate };
905         if timestamp > 0 {
906             Some(UNIX_EPOCH + Duration::from_secs(timestamp.into()))
907         } else {
908             None
909         }
910     }
911 
912     #[inline]
has_warning(&self) -> bool913     pub fn has_warning(&self) -> bool {
914         unsafe { (*self.as_raw()).warning() }
915     }
916 
917     #[inline]
has_update(&self) -> bool918     pub fn has_update(&self) -> bool {
919         unsafe { (*self.as_raw()).update() }
920     }
921 
922     #[inline]
is_urgent(&self) -> bool923     pub fn is_urgent(&self) -> bool {
924         unsafe { (*self.as_raw()).urgent() }
925     }
926 
927     #[inline]
has_noinfo(&self) -> bool928     pub fn has_noinfo(&self) -> bool {
929         unsafe { (*self.as_raw()).noinfo() }
930     }
931 
932     #[inline]
is_unknown(&self) -> bool933     pub fn is_unknown(&self) -> bool {
934         unsafe { (*self.as_raw()).unknown() }
935     }
936 
937     #[inline]
is_too_old(&self) -> bool938     pub fn is_too_old(&self) -> bool {
939         unsafe { (*self.as_raw()).tooold() }
940     }
941 
942     #[inline]
has_error(&self) -> bool943     pub fn has_error(&self) -> bool {
944         unsafe { (*self.as_raw()).error() }
945     }
946 }
947 
948 impl fmt::Debug for QuerySwdbResult {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result949     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
950         f.debug_struct("QuerySwdbResult")
951             .field("raw", &self.as_raw())
952             .field("name", &self.name_raw())
953             .field("installed_version", &self.installed_version_raw())
954             .field("latest_version", &self.latest_version_raw())
955             .field("creation_time", &self.creation_time())
956             .field("retrieval_time", &self.retrieval_time())
957             .field("release_time", &self.release_time())
958             .field("has_warning", &self.has_warning())
959             .field("has_update", &self.has_update())
960             .field("is_urgent", &self.is_urgent())
961             .field("has_noinfo", &self.has_noinfo())
962             .field("is_unknown", &self.is_unknown())
963             .field("is_too_old", &self.is_too_old())
964             .field("has_error", &self.has_error())
965             .finish()
966     }
967 }
968