diff options
author | Neal H. Walfield <neal@pep.foundation> | 2019-05-06 18:09:38 +0200 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2019-05-07 12:18:33 +0200 |
commit | 471932ab32ee8d76c7939e8fbb028dc9260ac3bb (patch) | |
tree | 9fc016949bd13b0953b30ce7ce40bed9b8414420 /openpgp-ffi/src/packet/userid.rs | |
parent | abffff28039cafcb076063790cf7458d5e3d0e2c (diff) |
openpgp-ffi: Add functions to extract the various parts of a User ID
- Add pgp_user_id_name, pgp_user_id_comment, pgp_user_id_address,
and pgp_user_id_address_normalized.
Diffstat (limited to 'openpgp-ffi/src/packet/userid.rs')
-rw-r--r-- | openpgp-ffi/src/packet/userid.rs | 181 |
1 files changed, 180 insertions, 1 deletions
diff --git a/openpgp-ffi/src/packet/userid.rs b/openpgp-ffi/src/packet/userid.rs index 15f0d0a2..49f586c0 100644 --- a/openpgp-ffi/src/packet/userid.rs +++ b/openpgp-ffi/src/packet/userid.rs @@ -4,8 +4,9 @@ //! //! [Section 5.11 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.11 -use libc::{uint8_t, size_t}; extern crate sequoia_openpgp as openpgp; +use libc::{uint8_t, c_char, size_t}; +use error::Status; use super::Packet; use RefRaw; @@ -27,3 +28,181 @@ pub extern "system" fn pgp_user_id_value(uid: *const Packet, panic!("Not a UserID packet"); } } + +/// Returns the User ID's display name, if any. +/// +/// The User ID is parsed as an [RFC 2822 mailbox], and the display +/// name is extracted. +/// +/// If the User ID is not a valid RFC 2822 mailbox production, +/// then an error is returned. +/// +/// If the User ID does not contain a display, *name is set +/// to NULL. +/// +/// [RFC 2822 mailbox]: https://tools.ietf.org/html/rfc2822#section-3.4 +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "system" fn pgp_user_id_name( + errp: Option<&mut *mut ::error::Error>, uid: *const Packet, + namep: &mut *mut c_char) + -> Status +{ + ffi_make_fry_from_errp!(errp); + let uid = uid.ref_raw(); + + if let &openpgp::Packet::UserID(ref uid) = uid { + match uid.name() { + Ok(Some(name)) => + *namep = ffi_return_string!(name), + Ok(None) => + *namep = ::std::ptr::null_mut(), + Err(err) => { + use MoveIntoRaw; + let status = ::error::Status::from(&err); + if let Some(errp) = errp { + *errp = err.move_into_raw(); + } + return status; + } + } + } else { + panic!("Not a UserID packet"); + } + + Status::Success +} + +/// Returns the User ID's comment, if any. +/// +/// The User ID is parsed as an [RFC 2822 mailbox], and the first +/// comment is extracted. +/// +/// If the User ID is not a valid RFC 2822 mailbox production, +/// then an error is returned. +/// +/// If the User ID does not contain a comment, *commentp is set +/// to NULL. +/// +/// [RFC 2822 mailbox]: https://tools.ietf.org/html/rfc2822#section-3.4 +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "system" fn pgp_user_id_comment( + errp: Option<&mut *mut ::error::Error>, uid: *const Packet, + commentp: &mut *mut c_char) + -> Status +{ + ffi_make_fry_from_errp!(errp); + let uid = uid.ref_raw(); + + if let &openpgp::Packet::UserID(ref uid) = uid { + match uid.comment() { + Ok(Some(comment)) => + *commentp = ffi_return_string!(comment), + Ok(None) => + *commentp = ::std::ptr::null_mut(), + Err(err) => { + use MoveIntoRaw; + let status = ::error::Status::from(&err); + if let Some(errp) = errp { + *errp = err.move_into_raw(); + } + return status; + } + } + } else { + panic!("Not a UserID packet"); + } + + Status::Success +} + +/// Returns the User ID's email address, if any. +/// +/// The User ID is parsed as an [RFC 2822 mailbox], and the email +/// address is extracted. +/// +/// If the User ID is not a valid RFC 2822 mailbox production, +/// then an error is returned. +/// +/// If the User ID does not contain an email address, *addressp is set +/// to NULL. +/// +/// [RFC 2822 mailbox]: https://tools.ietf.org/html/rfc2822#section-3.4 +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "system" fn pgp_user_id_address( + errp: Option<&mut *mut ::error::Error>, uid: *const Packet, + addressp: &mut *mut c_char) + -> Status +{ + ffi_make_fry_from_errp!(errp); + let uid = uid.ref_raw(); + + if let &openpgp::Packet::UserID(ref uid) = uid { + match uid.address() { + Ok(Some(address)) => + *addressp = ffi_return_string!(address), + Ok(None) => + *addressp = ::std::ptr::null_mut(), + Err(err) => { + use MoveIntoRaw; + let status = ::error::Status::from(&err); + if let Some(errp) = errp { + *errp = err.move_into_raw(); + } + return status; + } + } + } else { + panic!("Not a UserID packet"); + } + + Status::Success +} + +/// Returns a normalized version of the UserID's email address. +/// +/// Normalized email addresses are primarily needed when email +/// addresses are compared. +/// +/// Note: normalized email addresses are still valid email +/// addresses. +/// +/// This function normalizes an email address by doing [puny-code +/// normalization] on the domain, and lowercasing the local part in +/// the so-called [empty locale]. +/// +/// Note: this normalization procedure is the same as the +/// normalization procedure recommended by [Autocrypt]. +/// +/// [puny-code normalization]: https://tools.ietf.org/html/rfc5891.html#section-4.4 +/// [empty locale]: https://www.w3.org/International/wiki/Case_folding +/// [Autocryt]: https://autocrypt.org/level1.html#e-mail-address-canonicalization +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "system" fn pgp_user_id_address_normalized( + errp: Option<&mut *mut ::error::Error>, uid: *const Packet, + addressp: &mut *mut c_char) + -> Status +{ + ffi_make_fry_from_errp!(errp); + let uid = uid.ref_raw(); + + if let &openpgp::Packet::UserID(ref uid) = uid { + match uid.address_normalized() { + Ok(Some(address)) => + *addressp = ffi_return_string!(address), + Ok(None) => + *addressp = ::std::ptr::null_mut(), + Err(err) => { + use MoveIntoRaw; + let status = ::error::Status::from(&err); + if let Some(errp) = errp { + *errp = err.move_into_raw(); + } + return status; + } + } + } else { + panic!("Not a UserID packet"); + } + + Status::Success +} |