From 92a3f76dd0b8c856111e18cb03c3677eaba66399 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 27 Oct 2022 18:12:22 +0200 Subject: [PATCH] Cardholder name format handling belongs in openpgp-card-sequoia --- openpgp-card-sequoia/src/card.rs | 23 ++++++++++++------- tools/src/bin/opgpcard/commands/status.rs | 28 ++++++----------------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/openpgp-card-sequoia/src/card.rs b/openpgp-card-sequoia/src/card.rs index 7c6a9b1..ab48355 100644 --- a/openpgp-card-sequoia/src/card.rs +++ b/openpgp-card-sequoia/src/card.rs @@ -336,11 +336,16 @@ impl<'a> Card> { self.state.opt.cardholder_related_data() } + // Unicode codepoints are a superset of iso-8859-1 characters + fn latin1_to_string(s: &[u8]) -> String { + s.iter().map(|&c| c as char).collect() + } + /// Get cardholder name as a String (this also normalizes the "<" and "<<" filler chars) - pub fn cardholder_name(&mut self) -> Result { + pub fn cardholder_name(&mut self) -> Result, Error> { let crd = self.state.opt.cardholder_related_data()?; if let Some(name) = crd.name() { - let name = String::from_utf8_lossy(name).to_string(); + let name = Self::latin1_to_string(name); // re-format name ("last< = name.split("<<").collect(); @@ -349,9 +354,9 @@ impl<'a> Card> { // replace item separators with spaces let name = name.replace('<', " "); - Ok(name) + Ok(Some(name)) } else { - Ok("".to_string()) + Ok(None) } } @@ -555,15 +560,17 @@ impl<'app, 'open> Card> { impl Card> { pub fn set_name(&mut self, name: &str) -> Result<(), Error> { - if name.len() >= 40 { - return Err(Error::InternalError("name too long".into())); - } - // All chars must be in ASCII7 if name.chars().any(|c| !c.is_ascii()) { return Err(Error::InternalError("Invalid char in name".into())); }; + // FIXME: encode spaces and do ordering + + if name.len() >= 40 { + return Err(Error::InternalError("name too long".into())); + } + self.card().set_name(name.as_bytes()) } diff --git a/tools/src/bin/opgpcard/commands/status.rs b/tools/src/bin/opgpcard/commands/status.rs index 0331b54..19d3863 100644 --- a/tools/src/bin/opgpcard/commands/status.rs +++ b/tools/src/bin/opgpcard/commands/status.rs @@ -54,35 +54,21 @@ pub fn print_status( let version = ai.version().to_be_bytes(); output.card_version(format!("{}.{}", version[0], version[1])); - // card / cardholder metadata - let crd = card.cardholder_related_data()?; - - if let Some(name) = crd.name() { - // FIXME: decoding as utf8 is wrong (the spec defines this field as latin1 encoded) - let name = String::from_utf8_lossy(name).to_string(); - - // // This field is silly, maybe ignore it?! - // if let Some(sex) = crd.sex() { - // if sex == Sex::Male { - // print!("Mr. "); - // } else if sex == Sex::Female { - // print!("Mrs. "); - // } - // } - - // re-format name ("last< = name.split("<<").collect(); - let name = name.iter().cloned().rev().collect::>().join(" "); - + // Cardholder Name + if let Some(name) = card.cardholder_name()? { output.card_holder(name); } + // We ignore the Cardholder "Sex" field, because it's silly and mostly unhelpful + + // Certificate URL let url = card.url()?; if !url.is_empty() { output.url(url); } - if let Some(lang) = crd.lang() { + // Language Preference + if let Some(lang) = card.cardholder_related_data()?.lang() { for lang in lang { output.language_preference(format!("{}", lang)); }