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