Cardholder name format handling belongs in openpgp-card-sequoia

This commit is contained in:
Heiko Schaefer 2022-10-27 18:12:22 +02:00
parent d689ceb1dc
commit 92a3f76dd0
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
2 changed files with 22 additions and 29 deletions

View file

@ -336,11 +336,16 @@ impl<'a> Card<Transaction<'a>> {
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<String, Error> {
pub fn cardholder_name(&mut self) -> Result<Option<String>, 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<<first")
let name: Vec<_> = name.split("<<").collect();
@ -349,9 +354,9 @@ impl<'a> Card<Transaction<'a>> {
// 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<Admin<'app, 'open>> {
impl Card<Admin<'_, '_>> {
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())
}

View file

@ -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<<first")
let name: Vec<_> = name.split("<<").collect();
let name = name.iter().cloned().rev().collect::<Vec<_>>().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));
}