Compare commits
2 Commits
feat/38-fs
...
feat/37-fs
Author | SHA1 | Date | |
---|---|---|---|
2ad6dba535
|
|||
db5eedd45a
|
@ -2017,6 +2017,7 @@ name = "fsv"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"chrono",
|
||||||
"deku",
|
"deku",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"fsv-sys",
|
"fsv-sys",
|
||||||
@ -2034,6 +2035,7 @@ name = "fsv-sys"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen",
|
"bindgen",
|
||||||
|
"chrono",
|
||||||
"libc",
|
"libc",
|
||||||
"libloading 0.8.5",
|
"libloading 0.8.5",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -16,3 +16,6 @@ thiserror.workspace = true
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.70.1"
|
bindgen = "0.70.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
chrono = "0.4.38"
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
| SSV_InitLIB2 |
|
| SSV_InitLIB2 |
|
||||||
| SSV_LireConfig |
|
| SSV_LireConfig |
|
||||||
| SSV_LireCartePS |
|
| SSV_LireCartePS |
|
||||||
|
| SSV_LireDroitsVitale |
|
||||||
|
|
||||||
## SGD
|
## SGD
|
||||||
|
|
||||||
| Fonctions implémentées |
|
| Fonctions implémentées |
|
||||||
|------------------------|
|
|------------------------|
|
||||||
|
|
||||||
|
|
||||||
## SRT
|
## SRT
|
||||||
|
|
||||||
| Fonctions implémentées |
|
| Fonctions implémentées |
|
||||||
|
@ -109,6 +109,15 @@ impl SSVLibrary<V1_40_14> {
|
|||||||
pZDataOut: *mut *mut libc::c_void,
|
pZDataOut: *mut *mut libc::c_void,
|
||||||
pTailleZone: *mut usize
|
pTailleZone: *mut usize
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ssv_function!(BINDINGS_V1_40_14::SSV_LireDroitsVitale, ssv_lire_droits_vitale, {
|
||||||
|
NomRessourcePS: *const i8,
|
||||||
|
NomRessourceLecteur: *const i8,
|
||||||
|
CodePorteurPS: *const i8,
|
||||||
|
DateConsultation: *const i8,
|
||||||
|
pZDataOut: *mut *mut libc::c_void,
|
||||||
|
pTailleZone: *mut usize
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SSVLibrary<V1_40_13> {
|
impl SSVLibrary<V1_40_13> {
|
||||||
@ -128,6 +137,15 @@ impl SSVLibrary<V1_40_13> {
|
|||||||
pZDataOut: *mut *mut libc::c_void,
|
pZDataOut: *mut *mut libc::c_void,
|
||||||
pTailleZone: *mut usize
|
pTailleZone: *mut usize
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ssv_function!(BINDINGS_V1_40_13::SSV_LireDroitsVitale, ssv_lire_droits_vitale, {
|
||||||
|
NomRessourcePS: *const i8,
|
||||||
|
NomRessourceLecteur: *const i8,
|
||||||
|
CodePorteurPS: *const i8,
|
||||||
|
DateConsultation: *const i8,
|
||||||
|
pZDataOut: *mut *mut libc::c_void,
|
||||||
|
pTailleZone: *mut usize
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_library_path(version: &SupportedFsvVersion) -> String {
|
pub fn get_library_path(version: &SupportedFsvVersion) -> String {
|
||||||
@ -162,8 +180,14 @@ mod test {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
mod common {
|
||||||
fn test_initlib2() {
|
use super::*;
|
||||||
|
|
||||||
|
const CPS_READER_NAME: &str = "Gemalto PC Twin Reader (645D94C3) 00 00";
|
||||||
|
const CPS_PIN: &str = "1234";
|
||||||
|
const VITALE_READER_NAME: &str = "XXXXXX";
|
||||||
|
|
||||||
|
pub fn init_library() -> SSVLibrary<V1_40_13> {
|
||||||
let lib_path = &get_library_path(&SupportedFsvVersion::V1_40_13);
|
let lib_path = &get_library_path(&SupportedFsvVersion::V1_40_13);
|
||||||
let ssv_library = SSVLibrary::<V1_40_13>::new(lib_path).expect("SSVLibrary::new failed");
|
let ssv_library = SSVLibrary::<V1_40_13>::new(lib_path).expect("SSVLibrary::new failed");
|
||||||
|
|
||||||
@ -171,29 +195,24 @@ mod test {
|
|||||||
CString::new(sesam_ini_path(&SupportedFsvVersion::V1_40_13)).expect("CString::new failed");
|
CString::new(sesam_ini_path(&SupportedFsvVersion::V1_40_13)).expect("CString::new failed");
|
||||||
let result = unsafe { ssv_library.ssv_init_lib2(sesam_ini_str.as_ptr()) }.unwrap();
|
let result = unsafe { ssv_library.ssv_init_lib2(sesam_ini_str.as_ptr()) }.unwrap();
|
||||||
assert_eq!(result, 0);
|
assert_eq!(result, 0);
|
||||||
|
|
||||||
|
ssv_library
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn lire_config(ssv_library: &SSVLibrary<V1_40_13>) {
|
||||||
fn test_lire_config_and_carte_ps() {
|
|
||||||
let lib_path = &get_library_path(&SupportedFsvVersion::V1_40_13);
|
|
||||||
let ssv_library = SSVLibrary::<V1_40_13>::new(lib_path).expect("SSVLibrary::new failed");
|
|
||||||
|
|
||||||
let sesam_ini_str =
|
|
||||||
CString::new(sesam_ini_path(&SupportedFsvVersion::V1_40_13)).expect("CString::new failed");
|
|
||||||
let result = unsafe { ssv_library.ssv_init_lib2(sesam_ini_str.as_ptr()) }.unwrap();
|
|
||||||
assert_eq!(result, 0);
|
|
||||||
|
|
||||||
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
||||||
let mut size: libc::size_t = 0;
|
let mut size: libc::size_t = 0;
|
||||||
let result = unsafe { ssv_library.ssv_lire_config(&mut buffer_ptr, &mut size) }.unwrap();
|
let result = unsafe { ssv_library.ssv_lire_config(&mut buffer_ptr, &mut size) }.unwrap();
|
||||||
assert_eq!(result, 0);
|
assert_eq!(result, 0);
|
||||||
unsafe { libc::free(buffer_ptr) };
|
unsafe { libc::free(buffer_ptr) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lire_carte_ps(ssv_library: &SSVLibrary<V1_40_13>) {
|
||||||
let nom_ressource_ps =
|
let nom_ressource_ps =
|
||||||
CString::new("Gemalto PC Twin Reader (645D94C3) 00 00").expect("CString::new failed");
|
CString::new(CPS_READER_NAME).expect("CString::new failed");
|
||||||
let nom_ressource_lecteur =
|
let nom_ressource_lecteur =
|
||||||
CString::new("Gemalto PC Twin Reader (645D94C3) 00 00").expect("CString::new failed");
|
CString::new("useless parameter").expect("CString::new failed");
|
||||||
let code_porteur_ps = CString::new("1234").expect("CString::new failed");
|
let code_porteur_ps = CString::new(CPS_PIN).expect("CString::new failed");
|
||||||
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
||||||
let mut size: libc::size_t = 0;
|
let mut size: libc::size_t = 0;
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
@ -204,9 +223,60 @@ mod test {
|
|||||||
&mut buffer_ptr,
|
&mut buffer_ptr,
|
||||||
&mut size,
|
&mut size,
|
||||||
)
|
)
|
||||||
}
|
}.unwrap();
|
||||||
.unwrap();
|
|
||||||
assert_eq!(result, 0);
|
assert_eq!(result, 0);
|
||||||
unsafe { libc::free(buffer_ptr) };
|
unsafe { libc::free(buffer_ptr) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn lire_droits_vitale(ssv_library: &SSVLibrary<V1_40_13>) {
|
||||||
|
let nom_ressource_ps =
|
||||||
|
CString::new(CPS_READER_NAME).expect("CString::new failed");
|
||||||
|
let nom_ressource_lecteur =
|
||||||
|
CString::new(VITALE_READER_NAME).expect("CString::new failed");
|
||||||
|
let code_porteur_ps = CString::new(CPS_PIN).expect("CString::new failed");
|
||||||
|
// Today's date, in the format YYYYMMDD
|
||||||
|
let today = chrono::Local::now().format("%Y%m%d").to_string();
|
||||||
|
let date_consultation = CString::new(today).expect("CString::new failed");
|
||||||
|
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
||||||
|
let mut size: libc::size_t = 0;
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
ssv_library.ssv_lire_droits_vitale(
|
||||||
|
nom_ressource_ps.as_ptr(),
|
||||||
|
nom_ressource_lecteur.as_ptr(),
|
||||||
|
code_porteur_ps.as_ptr(),
|
||||||
|
date_consultation.as_ptr(),
|
||||||
|
&mut buffer_ptr,
|
||||||
|
&mut size,
|
||||||
|
)
|
||||||
|
}.unwrap();
|
||||||
|
assert_eq!(result, 0);
|
||||||
|
unsafe { libc::free(buffer_ptr) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_initlib2() {
|
||||||
|
let _ssv_library = common::init_library();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lire_config() {
|
||||||
|
let ssv_library = common::init_library();
|
||||||
|
common::lire_config(&ssv_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore="This test requires a CPS card to be inserted in the reader"]
|
||||||
|
fn test_lire_carte_ps() {
|
||||||
|
let ssv_library = common::init_library();
|
||||||
|
common::lire_carte_ps(&ssv_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore="This test requires a CPS card and a Vitale card to be inserted in the readers"]
|
||||||
|
fn test_lire_droits_vitale() {
|
||||||
|
let ssv_library = common::init_library();
|
||||||
|
common::lire_droits_vitale(&ssv_library);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ utils = { path = "../utils" }
|
|||||||
#[dev-dependencies]
|
#[dev-dependencies]
|
||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
env_logger = "0.11.5"
|
env_logger = "0.11.5"
|
||||||
|
chrono = "0.4.38"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = "1.40.0"
|
insta = "1.40.0"
|
||||||
|
@ -37,6 +37,9 @@ pub struct SSV {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SSV {
|
impl SSV {
|
||||||
|
const CPS_READER_NAME: &'static str = "Gemalto PC Twin Reader (645D94C3) 00 00";
|
||||||
|
const VITALE_READER_NAME: &'static str = "Gemalto PC Twin Reader (645D94C3) 00 00"; // TODO: Change this to the correct reader name
|
||||||
|
|
||||||
pub fn new(version: SupportedFsvVersion) -> Result<Self, Error> {
|
pub fn new(version: SupportedFsvVersion) -> Result<Self, Error> {
|
||||||
let library = match version {
|
let library = match version {
|
||||||
SupportedFsvVersion::V1_40_13 => {
|
SupportedFsvVersion::V1_40_13 => {
|
||||||
@ -77,18 +80,18 @@ impl SSV {
|
|||||||
/// # Read the CPS card
|
/// # Read the CPS card
|
||||||
/// Implement: SSV_LireCartePS
|
/// Implement: SSV_LireCartePS
|
||||||
pub fn read_professional_card(&self, pin_code: &str) -> Result<Data, Error> {
|
pub fn read_professional_card(&self, pin_code: &str) -> Result<Data, Error> {
|
||||||
let pcsc_reader_name = "Gemalto PC Twin Reader (645D94C3) 00 00";
|
|
||||||
|
|
||||||
let pin_code = CString::new(pin_code).expect("CString::new failed");
|
let pin_code = CString::new(pin_code).expect("CString::new failed");
|
||||||
let pcsc_reader_name = CString::new(pcsc_reader_name).expect("CString::new failed");
|
let cps_pcsc_reader_name = CString::new(SSV::CPS_READER_NAME).expect("CString::new failed");
|
||||||
|
let vitale_pcsc_reader_name = CString::new(SSV::VITALE_READER_NAME).expect("CString::new failed");
|
||||||
|
|
||||||
let mut out_buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
let mut out_buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
||||||
let mut out_buffer_size: libc::size_t = 0;
|
let mut out_buffer_size: libc::size_t = 0;
|
||||||
|
|
||||||
let result = match &self.library {
|
let result = match &self.library {
|
||||||
SsvLibraryVersion::V1_40_13(library) => {
|
SsvLibraryVersion::V1_40_13(library) => {
|
||||||
unsafe { library.ssv_lire_carte_ps(
|
unsafe { library.ssv_lire_carte_ps(
|
||||||
pcsc_reader_name.as_ptr(),
|
cps_pcsc_reader_name.as_ptr(),
|
||||||
pcsc_reader_name.as_ptr(),
|
vitale_pcsc_reader_name.as_ptr(),
|
||||||
pin_code.as_ptr(),
|
pin_code.as_ptr(),
|
||||||
&mut out_buffer_ptr,
|
&mut out_buffer_ptr,
|
||||||
&mut out_buffer_size)
|
&mut out_buffer_size)
|
||||||
@ -96,8 +99,8 @@ impl SSV {
|
|||||||
},
|
},
|
||||||
SsvLibraryVersion::V1_40_14(library) => {
|
SsvLibraryVersion::V1_40_14(library) => {
|
||||||
unsafe { library.ssv_lire_carte_ps(
|
unsafe { library.ssv_lire_carte_ps(
|
||||||
pcsc_reader_name.as_ptr(),
|
cps_pcsc_reader_name.as_ptr(),
|
||||||
pcsc_reader_name.as_ptr(),
|
vitale_pcsc_reader_name.as_ptr(),
|
||||||
pin_code.as_ptr(),
|
pin_code.as_ptr(),
|
||||||
&mut out_buffer_ptr,
|
&mut out_buffer_ptr,
|
||||||
&mut out_buffer_size)
|
&mut out_buffer_size)
|
||||||
@ -149,6 +152,58 @@ impl SSV {
|
|||||||
unsafe { libc::free(out_buffer_ptr) };
|
unsafe { libc::free(out_buffer_ptr) };
|
||||||
Ok(config_blocks)
|
Ok(config_blocks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_vitale_card_rights(&self, pin_code: &str) -> Result<Data, Error> {
|
||||||
|
let pin_code = CString::new(pin_code).expect("CString::new failed");
|
||||||
|
let cps_pcsc_reader_name = CString::new(SSV::CPS_READER_NAME).expect("CString::new failed");
|
||||||
|
let vitale_pcsc_reader_name = CString::new(SSV::VITALE_READER_NAME).expect("CString::new failed");
|
||||||
|
// Today's date, in the format YYYYMMDD
|
||||||
|
let today = chrono::Local::now().format("%Y%m%d").to_string();
|
||||||
|
let date_consultation = CString::new(today).expect("CString::new failed");
|
||||||
|
|
||||||
|
let mut out_buffer_ptr: *mut libc::c_void = ptr::null_mut();
|
||||||
|
let mut out_buffer_size: libc::size_t = 0;
|
||||||
|
|
||||||
|
let result = match &self.library {
|
||||||
|
SsvLibraryVersion::V1_40_13(library) => {
|
||||||
|
unsafe { library.ssv_lire_droits_vitale(
|
||||||
|
cps_pcsc_reader_name.as_ptr(),
|
||||||
|
vitale_pcsc_reader_name.as_ptr(),
|
||||||
|
pin_code.as_ptr(),
|
||||||
|
date_consultation.as_ptr(),
|
||||||
|
&mut out_buffer_ptr,
|
||||||
|
&mut out_buffer_size)
|
||||||
|
}?
|
||||||
|
},
|
||||||
|
SsvLibraryVersion::V1_40_14(library) => {
|
||||||
|
unsafe { library.ssv_lire_droits_vitale(
|
||||||
|
cps_pcsc_reader_name.as_ptr(),
|
||||||
|
vitale_pcsc_reader_name.as_ptr(),
|
||||||
|
pin_code.as_ptr(),
|
||||||
|
date_consultation.as_ptr(),
|
||||||
|
&mut out_buffer_ptr,
|
||||||
|
&mut out_buffer_size)
|
||||||
|
}?
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if result != 0 {
|
||||||
|
// Free memory
|
||||||
|
unsafe { libc::free(out_buffer_ptr) };
|
||||||
|
let error = SSVErrorCodes::from(result);
|
||||||
|
return Err(Error::SSVError(error));
|
||||||
|
}
|
||||||
|
// Parse the buffer into a Data struct
|
||||||
|
let buffer = unsafe { std::slice::from_raw_parts(out_buffer_ptr as *const u8, out_buffer_size) };
|
||||||
|
////////////////////////////
|
||||||
|
println!("{:?}", buffer);
|
||||||
|
////////////////////////////
|
||||||
|
let (_rest, vitale_blocks) = Data::from_bytes((buffer, 0)).unwrap();
|
||||||
|
|
||||||
|
// Free memory
|
||||||
|
unsafe { libc::free(out_buffer_ptr) };
|
||||||
|
Ok(vitale_blocks)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -185,7 +240,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore="
|
#[ignore="
|
||||||
WARNING: Read the card with PIN 1234 - Risk of blocking the card
|
WARNING: Read the card with PIN 1234 - Risk of blocking the card if it's not the right card
|
||||||
WARNING: This test will only work with GILBERT's PHARMOFFICE card (titulaire kit pharmacie)
|
WARNING: This test will only work with GILBERT's PHARMOFFICE card (titulaire kit pharmacie)
|
||||||
"]
|
"]
|
||||||
fn test_read_professional_card_good_pin() -> Result<()> {
|
fn test_read_professional_card_good_pin() -> Result<()> {
|
||||||
@ -214,7 +269,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore="WARNING: Read the card with PIN 0000 - Risk of blocking the card"]
|
#[ignore="WARNING: Read the card with PIN 0000 - Risk of blocking the card if it's not the right card"]
|
||||||
fn test_read_professional_card_bad_pin() -> Result<()> {
|
fn test_read_professional_card_bad_pin() -> Result<()> {
|
||||||
let lib = setup::init()?;
|
let lib = setup::init()?;
|
||||||
let pin_code = "0000";
|
let pin_code = "0000";
|
||||||
@ -246,4 +301,17 @@ mod tests {
|
|||||||
assert_eq!(header_content.ssv_version.0.revision, "20");
|
assert_eq!(header_content.ssv_version.0.revision, "20");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore="
|
||||||
|
WARNING: Read the card with PIN 1234 - Risk of blocking the card if it's not the right card
|
||||||
|
WARNING: This test needs a CPS and a VITALE card available simultaneously
|
||||||
|
"]
|
||||||
|
fn test_get_vitale_card_rights() -> Result<()> {
|
||||||
|
let lib = setup::init()?;
|
||||||
|
let pin_code = "1234";
|
||||||
|
let _cps_blocks = lib.read_professional_card(pin_code)?;
|
||||||
|
let _vitale_blocks = lib.get_vitale_card_rights(pin_code)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user