More explicit data type Lang for language.

This commit is contained in:
Heiko Schaefer 2022-02-16 10:02:35 +01:00
parent 889eedbb79
commit dcf73bd86d
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
7 changed files with 70 additions and 24 deletions

View file

@ -334,7 +334,7 @@ pub fn test_set_user_data(
card_client.set_name(b"Bar<<Foo")?;
// lang
card_client.set_lang(b"deen")?;
card_client.set_lang(&[['d', 'e'].into(), ['e', 'n'].into()])?;
// sex
card_client.set_sex(Sex::Female)?;
@ -348,7 +348,7 @@ pub fn test_set_user_data(
assert_eq!(ch.name().as_deref(), Some("Bar<<Foo".as_bytes()));
assert_eq!(
ch.lang().expect("Language setting is None"),
&[[b'd', b'e'], [b'e', b'n']]
&[['d', 'e'].into(), ['e', 'n'].into()]
);
assert_eq!(ch.sex(), Some(Sex::Female));

View file

@ -14,7 +14,7 @@ use openpgp_card::algorithm::{Algo, AlgoInfo, AlgoSimple};
use openpgp_card::card_do::{
ApplicationIdentifier, ApplicationRelatedData, CardholderRelatedData,
ExtendedCapabilities, ExtendedLengthInfo, Fingerprint, HistoricalBytes,
KeyGenerationTime, PWStatusBytes, SecuritySupportTemplate, Sex,
KeyGenerationTime, Lang, PWStatusBytes, SecuritySupportTemplate, Sex,
};
use openpgp_card::{CardClient, Error, KeySet, KeyType, Response};
@ -411,12 +411,12 @@ impl Admin<'_, '_> {
self.oc.card_client.set_name(name.as_bytes())
}
pub fn set_lang(&mut self, lang: &str) -> Result<Response, Error> {
pub fn set_lang(&mut self, lang: &[Lang]) -> Result<Response, Error> {
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<Response, Error> {

View file

@ -111,7 +111,7 @@ fn main() -> Result<(), Box<dyn Error>> {
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")?;

View file

@ -285,7 +285,7 @@ pub struct ExtendedLengthInfo {
#[derive(Debug, PartialEq)]
pub struct CardholderRelatedData {
name: Option<Vec<u8>>,
lang: Option<Vec<[u8; 2]>>,
lang: Option<Vec<Lang>>,
sex: Option<Sex>,
}
@ -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<Lang> for Vec<u8> {
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 {

View file

@ -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<Vec<u8>> =
tlv.find(&[0x5b].into()).map(|v| v.serialize().to_vec());
let lang: Option<Vec<[u8; 2]>> = tlv
.find(&[0x5f, 0x2d].into())
.map(|v| v.serialize().chunks(2).map(|c| [c[0], c[1]]).collect());
let lang: Option<Vec<Lang>> =
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<<Foo".as_bytes().to_vec()),
lang: Some(vec![[b'd', b'e'], [b'e', b'n']]),
lang: Some(vec![['d', 'e'].into(), ['e', 'n'].into()]),
sex: Some(Sex::Female)
}
);

View file

@ -48,7 +48,7 @@ use crate::apdu::commands;
use crate::apdu::response::RawResponse;
use crate::card_do::{
ApplicationRelatedData, CardholderRelatedData, Fingerprint,
KeyGenerationTime, PWStatusBytes, SecuritySupportTemplate, Sex,
KeyGenerationTime, Lang, PWStatusBytes, SecuritySupportTemplate, Sex,
};
use crate::crypto_data::{
CardUploadableKey, Cryptogram, Hash, PublicKeyMaterial,
@ -755,8 +755,14 @@ impl<'a> dyn CardClient + 'a {
apdu::send_command(self, put_name, false)?.try_into()
}
pub fn set_lang(&mut self, lang: &[u8]) -> Result<Response, Error> {
let put_lang = commands::put_lang(lang.to_vec());
pub fn set_lang(&mut self, lang: &[Lang]) -> Result<Response, Error> {
let bytes: Vec<u8> = lang
.iter()
.map(|&l| Into::<Vec<u8>>::into(l))
.flatten()
.collect();
let put_lang = commands::put_lang(bytes);
apdu::send_command(self, put_lang, false)?.try_into()
}

View file

@ -215,14 +215,7 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
}
if let Some(lang) = crd.lang() {
let lang = lang
.iter()
.map(|lang| {
lang.iter().map(|&u| char::from(u)).collect::<String>()
})
.collect::<Vec<_>>()
.join(", ");
println!("Language preferences '{}'", lang);
println!("Language preferences '{:?}'", lang);
}
// information about subkeys