From 016ae4340205242fa142b5644cf9e25b77a4f720 Mon Sep 17 00:00:00 2001 From: lienjukaisim <154924955+lienjukaisim@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:46:58 +0200 Subject: [PATCH] feat: implement some more structured version of the memory decoding and the mapping to CPS fields --- crates/sesam-vitale/src/ssvlib_demo.rs | 223 ++++++++++++++++++++++++- 1 file changed, 218 insertions(+), 5 deletions(-) diff --git a/crates/sesam-vitale/src/ssvlib_demo.rs b/crates/sesam-vitale/src/ssvlib_demo.rs index 21f5a94..16b6e42 100644 --- a/crates/sesam-vitale/src/ssvlib_demo.rs +++ b/crates/sesam-vitale/src/ssvlib_demo.rs @@ -101,11 +101,13 @@ impl Default for SituationPS { } } -fn ssv_lire_carte_ps() { + + +fn ssv_lire_carte_ps(code_pin :&str, lecteur :&str) { let resource_ps = - CString::new("HID Global OMNIKEY 3x21 Smart Card Reader 0").expect("CString::new failed"); + CString::new(lecteur).expect("CString::new failed"); let resource_reader = CString::new("").expect("CString::new failed"); - let card_number = CString::new("1234").expect("CString::new failed"); + let card_number = CString::new(code_pin).expect("CString::new failed"); let mut buffer: *mut c_void = ptr::null_mut(); let mut size: size_t = 0; @@ -126,8 +128,40 @@ fn ssv_lire_carte_ps() { } } decode_zone_memoire(hex_values); + + /* IDÉE : implémenter decode_zone_memoire sous forme d'itérateur + for (group, group_rank) in decode_zone_memoire(...) { + for (field, field_rank) in group { + match group_rank { + GROUP_1: { + match field_rank { + 1 => carte_ps.titulaire.type_de_carte_ps = field.into(), + 2 => carte_ps.titulaire.type_d_identification_nationale = field.into(), + 3 => carte_ps.titulaire.numero_d_identification_nationale = field.into(), + 4 => carte_ps.titulaire.cle_du_numero_d_identification_nationale = field.into(), + 5 => carte_ps.titulaire.code_civilite = field.into(), + 6 => carte_ps.titulaire.nom_du_ps = field.into(), + 7 => carte_ps.titulaire.prenom_du_ps = field.into(), + 8 => carte_ps.titulaire.categorie_carte = field.into(), + _ => (), + } + } + GROUP_2: { + match field_rank { + ... + } + } + } + } + } + */ } +/** + * Options possibles : + * - Passer un objet de type variable (CartePS, CarteVitale...) et le remplir intelligemment + * - Retourner un itérateur et faire le remplissage en dehors de decode_zone_memoire + */ pub fn decode_zone_memoire(bytes: &[u8]) { // Maintenant, vous pouvez accéder aux octets individuels dans `donnees` let mut current_pos_general = 0; @@ -389,11 +423,190 @@ pub fn demo() { let manifest_path = PathBuf::from(manifest_dir); dotenv::from_path(manifest_path.join(".env")).ok(); - println!("------- Demo for the SSV library --------"); + println!("------- Demo for the SSV library 2 --------"); ssv_init_lib_2(); - ssv_lire_carte_ps(); + let code_pin = "1234"; + let lecteur = "HID Global OMNIKEY 3x21 Smart Card Reader 0"; + let carte_ps = ssv_lire_carte_ps2(code_pin, lecteur); + println!("CartePS: {:#?}", carte_ps); // ssv_lire_config(); println!("-----------------------------------------"); } + + +struct field{ + rank : i32, + value : Vec +} +impl Default for field { + fn default() -> Self { + Self {rank: 0, + value: Vec::new(), + } + } +} +pub struct group{ + rank : i32, + fields : Vec +} +impl Default for group { + fn default() -> Self { + Self {rank: 0, + fields: Vec::new(), + } + } +} + + pub fn decode_zone_memoire2(bytes: &[u8]) -> Vec{ + + let mut current_pos_general = 0; + let mut current_groupe = 0; + let mut num_champ = 0; + let mut longueur_groupe: usize; + let mut current_pos_groupe = 0; + let mut groups : Vec = Vec::new(); + + while current_pos_general < (bytes.len() - 1) { + num_champ = 0; + current_groupe = + 256 * bytes[current_pos_general] as i32 + bytes[current_pos_general + 1 ] as i32; + current_pos_general += 2; + + groups.push(group::default()); + groups.last_mut().unwrap().rank=current_groupe; + + if bytes[current_pos_general] < 128 { + longueur_groupe = bytes[current_pos_general] as usize; + } else { + let nbre_octets_longueur = bytes[current_pos_general] - 128; + longueur_groupe = (0..nbre_octets_longueur).fold(0, |acc, i| { + current_pos_general += 1; + acc + (256_i32.pow(i as u32) * bytes[current_pos_general] as i32) as usize + }); + } + current_pos_general += 1; + println!("------- 3--------"); + current_pos_groupe = 0; + while current_pos_groupe < longueur_groupe { + num_champ += 1; + let longueur_champs: usize; + let nbre_octets_longueur: usize; + if bytes[current_pos_general] < 128 { + longueur_champs = bytes[current_pos_general] as usize; + nbre_octets_longueur = 1; + } else { + nbre_octets_longueur = bytes[current_pos_general] as usize - 128; + longueur_champs = (0..nbre_octets_longueur).fold(0, |acc, i| { + current_pos_general += 1; + current_pos_groupe += 1; + acc + (256_i32.pow(i as u32) * bytes[current_pos_general] as i32) as usize + }); + } + + groups.last_mut().unwrap().fields.push(field::default()); + groups.last_mut().unwrap().fields.last_mut().unwrap().rank=num_champ; + + if longueur_champs > 0 { + let mut bytes_champ = vec![0; longueur_champs]; + bytes_champ.copy_from_slice( + &bytes[current_pos_general + nbre_octets_longueur + ..current_pos_general + nbre_octets_longueur + longueur_champs], + ); + + //groups.last_mut().unwrap().fields.last_mut().unwrap().value= String::from_utf8_lossy(&bytes_champ).to_string(); + groups.last_mut().unwrap().fields.last_mut().unwrap().value= bytes_champ; + + + } + current_pos_general += longueur_champs + nbre_octets_longueur; + current_pos_groupe += longueur_champs + nbre_octets_longueur; + } + } + groups +} + +fn ssv_lire_carte_ps2(code_pin :&str, lecteur :&str) -> CartePS{ + let resource_ps = CString::new(lecteur).expect("CString::new failed"); + let resource_reader = CString::new("").expect("CString::new failed"); + let card_number = CString::new(code_pin).expect("CString::new failed"); + + let mut buffer: *mut c_void = ptr::null_mut(); + let mut size: size_t = 0; + let mut hex_values: &[u8] = &[]; + unsafe { + let result = SSV_LireCartePS( + resource_ps.as_ptr(), + resource_reader.as_ptr(), + card_number.as_ptr(), + &mut buffer, + &mut size, + ); + println!("SSV_LireCartePS result: {}", result); + + if !buffer.is_null() { + hex_values = std::slice::from_raw_parts(buffer as *const u8, size); + libc::free(buffer); + } + } + let groups= decode_zone_memoire2(hex_values); + let mut carte_ps = CartePS { + titulaire: TitulairePS { + type_de_carte_ps: String::new(), + type_d_identification_nationale: String::new(), + numero_d_identification_nationale: String::new(), + cle_du_numero_d_identification_nationale: String::new(), + code_civilite: String::new(), + nom_du_ps: String::new(), + prenom_du_ps: String::new(), + categorie_carte: ' ', + }, + situations: Vec::new(), +}; +for item_group in groups.iter(){ + for item_field in item_group.fields.iter(){ + match (item_group.rank,item_field.rank) { + (1, 1) => {carte_ps.titulaire.type_de_carte_ps = String::from_utf8_lossy(&item_field.value).to_string();} + (1, 2) => {carte_ps.titulaire.type_d_identification_nationale = String::from_utf8_lossy(&item_field.value).to_string();} + (1, 3) => {carte_ps.titulaire.numero_d_identification_nationale = String::from_utf8_lossy(&item_field.value).to_string();} + (1, 4) => {carte_ps.titulaire.cle_du_numero_d_identification_nationale = String::from_utf8_lossy(&item_field.value).to_string();} + (1, 5) => {carte_ps.titulaire.code_civilite = String::from_utf8_lossy(&item_field.value).to_string();} + (1, 6) => {carte_ps.titulaire.nom_du_ps = String::from_utf8_lossy(&item_field.value).to_string();} + (1, 7) => {carte_ps.titulaire.prenom_du_ps = String::from_utf8_lossy(&item_field.value).to_string();} + (1, 8) => unsafe {carte_ps.titulaire.categorie_carte = char::from_u32_unchecked(item_field.value[0] as u32)} + (2, 1) => {carte_ps.situations.push(SituationPS::default()); + carte_ps.situations.last_mut().unwrap().numero_logique_de_la_situation_de_facturation_du_ps = item_field.value[0];} + (2, 2) => {carte_ps.situations.last_mut().unwrap().mode_d_exercice = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 3) => {carte_ps.situations.last_mut().unwrap().statut_d_exercice = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 4) => {carte_ps.situations.last_mut().unwrap().secteur_d_activite = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 5) => {carte_ps.situations.last_mut().unwrap().type_d_identification_structure = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 6) => {carte_ps.situations.last_mut().unwrap().numero_d_identification_structure = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 7) => {carte_ps.situations.last_mut().unwrap().cle_du_numero_d_identification_structure = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 8) => {carte_ps.situations.last_mut().unwrap().raison_sociale_structure = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 9) => {carte_ps.situations.last_mut().unwrap().numero_d_identification_de_facturation_du_ps = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 10) => {carte_ps.situations.last_mut().unwrap().cle_du_numero_d_identification_de_facturation_du_ps = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 11) => {carte_ps.situations.last_mut().unwrap().numero_d_identification_du_ps_remplaçant = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 12) => {carte_ps.situations.last_mut().unwrap().cle_du_numero_d_identification_du_ps_remplaçant = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 13) => {carte_ps.situations.last_mut().unwrap().code_conventionnel = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 14) => {carte_ps.situations.last_mut().unwrap().code_specialite = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 15) => {carte_ps.situations.last_mut().unwrap().code_zone_tarifaire = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 16) => {carte_ps.situations.last_mut().unwrap().code_zone_ik = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 17) => {carte_ps.situations.last_mut().unwrap().code_agrement_1 = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 18) => {carte_ps.situations.last_mut().unwrap().code_agrement_2 = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 19) => {carte_ps.situations.last_mut().unwrap().code_agrement_3 = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 20) => {carte_ps.situations.last_mut().unwrap().habilitation_à_signer_une_facture = String::from_utf8_lossy(&item_field.value).to_string();} + (2, 21) => {carte_ps.situations.last_mut().unwrap().habilitation_à_signer_un_lot = String::from_utf8_lossy(&item_field.value).to_string();} + _ => (), + } + } +} +carte_ps + +} + + + + + +