1use crate::{
2 config::{CertificateConfig, PrintConfig},
3 error_code::ErrorCode,
4 response::{EricResponse, ResponseBuffer},
5 utils::ToCString,
6 ProcessingFlag,
7};
8use anyhow::{anyhow, Context};
9use eric_bindings::{EricBearbeiteVorgang, EricBeende, EricDekodiereDaten, EricInitialisiere};
10use std::{
11 env::{self},
12 path::Path,
13 ptr,
14};
15
16pub struct Eric;
20
21impl Eric {
22 pub fn new(log_path: &Path) -> Result<Self, anyhow::Error> {
24 println!("Initializing eric");
25
26 let plugin_path =
27 env::var("PLUGIN_PATH").context("Missing environment variable 'PLUGIN_PATH'")?;
28 let plugin_path = Path::new(&plugin_path);
29
30 println!("Setting plugin path '{}'", plugin_path.display());
31 println!("Setting log path '{}'", log_path.display());
32 println!("Logging to '{}'", log_path.join("eric.log").display());
33
34 let plugin_path = plugin_path.try_to_cstring()?;
35 let log_path = log_path.try_to_cstring()?;
36
37 let error_code = unsafe { EricInitialisiere(plugin_path.as_ptr(), log_path.as_ptr()) };
38
39 match error_code {
40 x if x == ErrorCode::ERIC_OK as i32 => Ok(Eric),
41 error_code => Err(anyhow!("Can't init eric: {}", error_code)),
42 }
43 }
44
45 pub fn validate(
49 &self,
50 xml: String,
51 taxonomy_type: &str,
52 taxonomy_version: &str,
53 pdf_path: Option<&str>,
54 ) -> Result<EricResponse, anyhow::Error> {
55 let processing_flag: ProcessingFlag;
56 let type_version = format!("{}_{}", taxonomy_type, taxonomy_version);
57 let print_config = if let Some(pdf_path) = pdf_path {
58 processing_flag = ProcessingFlag::Print;
59 Some(PrintConfig::new(pdf_path, &processing_flag)?)
60 } else {
61 processing_flag = ProcessingFlag::Validate;
62 None
63 };
64 Self::process(xml, type_version, processing_flag, print_config, None, None)
65 }
66
67 pub fn send(
74 &self,
75 xml: String,
76 taxonomy_type: &str,
77 taxonomy_version: &str,
78 pdf_path: Option<&str>,
79 ) -> Result<EricResponse, anyhow::Error> {
80 let certificate_path = env::var("CERTIFICATE_PATH")
81 .context("Missing environment variable 'CERTIFICATE_PATH'")?;
82 let certificate_password = env::var("CERTIFICATE_PASSWORD")
83 .context("Missing environment variable 'CERTIFICATE_PASSWORD'")?;
84
85 let processing_flag: ProcessingFlag;
86 let type_version = format!("{}_{}", taxonomy_type, taxonomy_version);
87 let print_config = if let Some(pdf_path) = pdf_path {
88 processing_flag = ProcessingFlag::SendAndPrint;
89 Some(PrintConfig::new(pdf_path, &processing_flag)?)
90 } else {
91 processing_flag = ProcessingFlag::Send;
92 None
93 };
94 let certificate_config = CertificateConfig::new(&certificate_path, &certificate_password)?;
95 Self::process(
96 xml,
97 type_version,
98 processing_flag,
99 print_config,
100 Some(certificate_config),
101 None,
102 )
103 }
104
105 #[allow(dead_code)]
106 fn decrypt(
107 &self,
108 encrypted_file: &str,
109 certificate_config: CertificateConfig,
110 ) -> Result<i32, anyhow::Error> {
111 let encrypted_data = encrypted_file.try_to_cstring()?;
112 let response_buffer = ResponseBuffer::new()?;
113
114 let error_code = unsafe {
115 EricDekodiereDaten(
116 certificate_config.certificate.handle,
117 certificate_config.password.as_ptr(),
118 encrypted_data.as_ptr(),
119 response_buffer.as_ptr(),
120 )
121 };
122
123 Ok(error_code)
124 }
125
126 fn process(
127 xml: String,
128 type_version: String,
129 processing_flag: ProcessingFlag,
130 print_config: Option<PrintConfig>,
131 certificate_config: Option<CertificateConfig>,
132 transfer_code: Option<u32>,
133 ) -> Result<EricResponse, anyhow::Error> {
134 println!("Processing xml file");
135
136 match processing_flag {
137 ProcessingFlag::Validate => println!("Validating xml file"),
138 ProcessingFlag::Print => println!("Validating xml file"),
139 ProcessingFlag::Send => println!("Sending xml file"),
140 ProcessingFlag::SendAndPrint => println!("Send and print"),
141 ProcessingFlag::CheckHints => println!("Check hints"),
142 ProcessingFlag::ValidateWithoutDate => {
143 println!("Validate without release date (German: Validiere ohne Freigabadatum)")
144 }
145 }
146
147 let xml = xml.try_to_cstring()?;
148 let type_version = type_version.try_to_cstring()?;
149
150 let transfer_code = match transfer_code {
153 Some(mut code) => &mut code,
154 None => ptr::null::<u32>() as *mut u32,
155 };
156
157 match &print_config {
158 Some(print_config) => println!(
159 "Printing confirmation to file '{}'",
160 print_config.pdf_path.to_str()?
161 ),
162 None => (),
163 }
164
165 let validation_response_buffer = ResponseBuffer::new()?;
166 let server_response_buffer = ResponseBuffer::new()?;
167
168 let error_code = unsafe {
169 EricBearbeiteVorgang(
170 xml.as_ptr(),
171 type_version.as_ptr(),
172 processing_flag.into_u32(),
173 match &print_config {
177 Some(el) => el.print_parameter.as_ptr(),
178 None => ptr::null(),
179 },
180 match &certificate_config {
184 Some(el) => el.certificate_parameter.as_ptr(),
185 None => ptr::null(),
186 },
187 transfer_code,
188 validation_response_buffer.as_ptr(),
189 server_response_buffer.as_ptr(),
190 )
191 };
192
193 let transfer_code = unsafe { transfer_code.as_ref() };
196
197 if let Some(code) = transfer_code {
198 println!("Transfer code: {}", code)
199 }
200
201 let validation_response = validation_response_buffer.read()?;
202 let server_response = server_response_buffer.read()?;
204 let response = EricResponse::new(
205 error_code,
206 validation_response.to_string(),
207 server_response.to_string(),
208 );
209
210 Ok(response)
211 }
212}
213
214impl Drop for Eric {
215 fn drop(&mut self) {
216 println!("Closing eric");
217
218 let error_code = unsafe { EricBeende() };
221
222 match error_code {
223 x if x == ErrorCode::ERIC_OK as i32 => (),
224 error_code => panic!("Can't close eric: {}", error_code),
225 }
226 }
227}