diff --git a/card-functionality/src/tests.rs b/card-functionality/src/tests.rs index 4a9613e..004625d 100644 --- a/card-functionality/src/tests.rs +++ b/card-functionality/src/tests.rs @@ -334,7 +334,7 @@ pub fn test_set_user_data( card_client.set_name(b"Bar< { self.oc.card_client.set_name(name.as_bytes()) } - pub fn set_lang(&mut self, lang: &str) -> Result { + pub fn set_lang(&mut self, lang: &[Lang]) -> Result { if lang.len() > 8 { return Err(anyhow!("lang too long").into()); } - self.oc.card_client.set_lang(lang.as_bytes()) + self.oc.card_client.set_lang(lang) } pub fn set_sex(&mut self, sex: Sex) -> Result { diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index 558c133..f3e0bc1 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -111,7 +111,7 @@ fn main() -> Result<(), Box> { let res = admin.set_sex(Sex::NotApplicable)?; println!("set sex {:x?}", res); - let res = admin.set_lang("en")?; + let res = admin.set_lang(&[['e', 'n'].into()])?; println!("set lang {:x?}", res); let res = admin.set_url("https://keys.openpgp.org")?; diff --git a/openpgp-card/src/card_do.rs b/openpgp-card/src/card_do.rs index 9e1aeef..65a3f87 100644 --- a/openpgp-card/src/card_do.rs +++ b/openpgp-card/src/card_do.rs @@ -285,7 +285,7 @@ pub struct ExtendedLengthInfo { #[derive(Debug, PartialEq)] pub struct CardholderRelatedData { name: Option>, - lang: Option>, + lang: Option>, sex: Option, } @@ -298,6 +298,45 @@ pub enum Sex { NotApplicable, } +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum Lang { + Value([u8; 2]), + Invalid(u8), +} + +impl From<(char, char)> for Lang { + fn from(c: (char, char)) -> Self { + Lang::Value([c.0 as u8, c.1 as u8]) + } +} + +impl From<[char; 2]> for Lang { + fn from(c: [char; 2]) -> Self { + Lang::Value([c[0] as u8, c[1] as u8]) + } +} + +impl From for Vec { + fn from(lang: Lang) -> Self { + match lang { + Lang::Value(v) => vec![v[0], v[1]], + Lang::Invalid(v) => vec![v], + } + } +} + +impl From<&[u8; 1]> for Lang { + fn from(data: &[u8; 1]) -> Self { + Lang::Invalid(data[0]) + } +} + +impl From<&[u8; 2]> for Lang { + fn from(data: &[u8; 2]) -> Self { + Lang::Value([data[0], data[1]]) + } +} + impl From<&Sex> for u8 { fn from(sex: &Sex) -> u8 { match sex { diff --git a/openpgp-card/src/card_do/cardholder.rs b/openpgp-card/src/card_do/cardholder.rs index cd6834d..434526f 100644 --- a/openpgp-card/src/card_do/cardholder.rs +++ b/openpgp-card/src/card_do/cardholder.rs @@ -7,7 +7,7 @@ use std::convert::TryFrom; use anyhow::Result; -use crate::card_do::{CardholderRelatedData, Sex}; +use crate::card_do::{CardholderRelatedData, Lang, Sex}; use crate::tlv::{value::Value, Tlv}; impl CardholderRelatedData { @@ -15,7 +15,7 @@ impl CardholderRelatedData { self.name.as_deref() } - pub fn lang(&self) -> Option<&[[u8; 2]]> { + pub fn lang(&self) -> Option<&[Lang]> { self.lang.as_deref() } @@ -34,9 +34,17 @@ impl TryFrom<&[u8]> for CardholderRelatedData { let name: Option> = tlv.find(&[0x5b].into()).map(|v| v.serialize().to_vec()); - let lang: Option> = tlv - .find(&[0x5f, 0x2d].into()) - .map(|v| v.serialize().chunks(2).map(|c| [c[0], c[1]]).collect()); + let lang: Option> = + tlv.find(&[0x5f, 0x2d].into()).map(|v| { + v.serialize() + .chunks(2) + .map(|c| match c.len() { + 2 => Lang::from(&[c[0], c[1]]), + 1 => Lang::from(&[c[0]]), + _ => unreachable!(), + }) + .collect() + }); let sex = tlv .find(&[0x5f, 0x35].into()) @@ -66,7 +74,7 @@ mod test { ch, CardholderRelatedData { name: Some("Bar< dyn CardClient + 'a { apdu::send_command(self, put_name, false)?.try_into() } - pub fn set_lang(&mut self, lang: &[u8]) -> Result { - let put_lang = commands::put_lang(lang.to_vec()); + pub fn set_lang(&mut self, lang: &[Lang]) -> Result { + let bytes: Vec = lang + .iter() + .map(|&l| Into::>::into(l)) + .flatten() + .collect(); + + let put_lang = commands::put_lang(bytes); apdu::send_command(self, put_lang, false)?.try_into() } diff --git a/tools/src/bin/opgpcard/main.rs b/tools/src/bin/opgpcard/main.rs index 08f2f4b..935cdca 100644 --- a/tools/src/bin/opgpcard/main.rs +++ b/tools/src/bin/opgpcard/main.rs @@ -215,14 +215,7 @@ fn print_status(ident: Option, verbose: bool) -> Result<()> { } if let Some(lang) = crd.lang() { - let lang = lang - .iter() - .map(|lang| { - lang.iter().map(|&u| char::from(u)).collect::() - }) - .collect::>() - .join(", "); - println!("Language preferences '{}'", lang); + println!("Language preferences '{:?}'", lang); } // information about subkeys