diff --git a/src/checks/mod.rs b/src/checks/mod.rs index c1c9218..2729565 100644 --- a/src/checks/mod.rs +++ b/src/checks/mod.rs @@ -22,10 +22,15 @@ * SOFTWARE. */ -pub mod osc; +use std::fmt::{Display, Formatter}; +use std::path::Path; use console::style; -use std::fmt::{Display, Formatter}; +use deob::deobfuscate; + +#[cfg(feature = "unzip-osb")] +pub mod osb; +pub mod osc; pub enum CheckNotice { /// This will result in Error if importing file and has a support code @@ -40,12 +45,16 @@ pub enum CheckNotice { description: String, line: Option, }, - #[allow(dead_code)] /// Other known issues Warning { description: String, line: Option, }, + /// Other known issues + Info { + description: String, + line: Option, + }, } impl Display for CheckNotice { @@ -59,7 +68,7 @@ impl Display for CheckNotice { } => match line { Some(line) => write!( f, - "{} ({}) at Line {}: {}{}", + "{: <7} ({}) at Line {}: {}{}", style("ERROR").red().bold(), code, line, @@ -71,7 +80,7 @@ impl Display for CheckNotice { ), None => write!( f, - "{} ({}): {}{}", + "{: <7} ({}): {}{}", style("ERROR").red().bold(), code, description, @@ -84,22 +93,37 @@ impl Display for CheckNotice { CheckNotice::Error { description, line } => match line { Some(line) => write!( f, - "{} at Line {}: {}", + "{: <7} at Line {}: {}", style("ERROR").red().bold(), line, description ), - None => write!(f, "{}: {}", style("ERROR").red().bold(), description), + None => write!(f, "{: <7} {}", style("ERROR").red().bold(), description), }, CheckNotice::Warning { description, line } => match line { Some(line) => write!( f, - "{} at Line {}: {}", + "{: <7} at Line {}: {}", style("WARNING").yellow().bold(), line, description ), - None => write!(f, "{}: {}", style("WARNING").yellow().bold(), description), + None => write!( + f, + "{: <7} {}", + style("WARNING").yellow().bold(), + description + ), + }, + CheckNotice::Info { description, line } => match line { + Some(line) => write!( + f, + "{: <7} at Line {}: {}", + style("INFO").blue().bold(), + line, + description + ), + None => write!(f, "{: <7} {}", style("INFO").blue().bold(), description), }, } } @@ -113,6 +137,27 @@ pub trait Fixable { fn fix(&mut self) -> bool; } +pub fn check_file(file: &Path, password: Option) -> Vec { + match file.extension() { + Some(ex) => match ex.to_str() { + #[cfg(feature = "unzip-osb")] + Some("osb") => match password { + Some(password) => osb::check_file(file, password.as_str()), + None => osb::check_file(file, deobfuscate(env!("OSB_KEY").trim()).as_str()), + }, + Some("osc") => osc::check_file(file), + _ => vec![CheckNotice::Error { + description: "Keine prüfbare Datei".to_string(), + line: None, + }], + }, + _ => vec![CheckNotice::Error { + description: "Keine prüfbare Datei".to_string(), + line: None, + }], + } +} + pub fn print_checks() { println!( "{}", @@ -144,17 +189,34 @@ pub fn print_checks() { } } - vec![Problem { - code: "2023-0001", - name: "Leerzeichen am Ende der Plausibilitätsregel-Bezeichnung (OSTARSUPP-13334)", - description: "Treten Leerzeichen am Ende der Plausibilitätsregel-Bezeichnung auf,\n\ - führt dies zu Fehlern beim Import der OSC-Datei.\n\ - \n\ - Das Problem wird beim Verwenden des Unterbefehls 'modify' automatisch\n\ - behoben und Leerzeichen entfernt. - ", - fixable: true, - }] + vec![ + Problem { + code: "2023-0001", + name: "Unterformular mit Markierung 'hat Unterformulare'", + description: " Aktuell gibt es keine Unterformulare in Unterformularen, daher\n \ + sollte dies nicht vorkommen.", + fixable: false, + }, + Problem { + code: "2023-0002", + name: "Formular hat keine Angabe zum Prozedurdatum", + description: " Formulare benötigen die Angabe des Prozedurdatums, anderenfalls\n \ + führt dies zu Problemen in Onkostar.\n\n \ + Unterformulare können ein Prozedurdatum haben, müssen es aber nicht.", + fixable: false, + }, + Problem { + code: "2023-0003", + name: "Leerzeichen am Ende der Plausibilitätsregel-Bezeichnung (OSTARSUPP-13334)", + description: + " Treten Leerzeichen am Ende der Plausibilitätsregel-Bezeichnung auf,\n \ + führt dies zu Fehlern beim Import der OSC-Datei.\n\n \ + Das Problem wird beim Verwenden des Unterbefehls 'modify' automatisch\n \ + behoben und Leerzeichen entfernt. + ", + fixable: true, + }, + ] .iter() .for_each(|problem| println!("{}\n", problem)) } diff --git a/src/checks/osb.rs b/src/checks/osb.rs new file mode 100644 index 0000000..f747a80 --- /dev/null +++ b/src/checks/osb.rs @@ -0,0 +1,80 @@ +/* + * MIT License + * + * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use std::fs; +use std::io::Read; +use std::path::Path; + +use crate::checks::{osc, CheckNotice}; + +#[cfg(feature = "unzip-osb")] +pub fn check_file(file: &Path, password: &str) -> Vec { + let file = match fs::File::open(file) { + Ok(file) => file, + Err(err) => { + return vec![CheckNotice::Error { + description: format!("Kann Datei nicht lesen: {}", err), + line: None, + }]; + } + }; + + let mut archive = match zip::ZipArchive::new(file) { + Ok(file) => file, + Err(err) => { + return vec![CheckNotice::Error { + description: format!("Kann Datei nicht lesen: {}", err), + line: None, + }]; + } + }; + + let mut result = vec![]; + + for i in 0..archive.len() { + if let Ok(Ok(mut zip_file)) = archive.by_index_decrypt(i, password.as_bytes()) { + if zip_file.is_file() && zip_file.name().ends_with(".osc") { + result.push(CheckNotice::Info { + description: format!("Prüfe Eintrag '{}'", zip_file.name()), + line: None, + }); + let mut buf = String::new(); + let _ = zip_file.read_to_string(&mut buf); + result.append(&mut osc::check(buf)); + continue; + } + result.push(CheckNotice::Warning { + description: format!("Überspringe Eintrag '{}'", zip_file.name()), + line: None, + }) + } else { + return vec![CheckNotice::Error { + description: format!("Kann Datei nicht lesen"), + line: None, + }]; + } + } + + result +} diff --git a/src/cli.rs b/src/cli.rs index 31fe61f..60e7977 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -109,6 +109,12 @@ pub enum SubCommand { #[command(about = "Überprüfe OSC-Datei auf bekannte Problemen")] Check { file: String, + #[arg( + short = 'p', + long = "password", + help = "Passwort der OSB-Datei (Optional - für OSB-Dateien)" + )] + password: Option, #[arg( long = "list", help = "Prüfe nicht und zeige Liste mit Checks auf bekannte Problemen" diff --git a/src/main.rs b/src/main.rs index 33502d4..be5dd18 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,8 +31,7 @@ use std::ops::Add; use std::path::{Path, PathBuf}; use std::str::FromStr; -use crate::checks::osc::check; -use crate::checks::print_checks; +use crate::checks::{check_file, print_checks, CheckNotice}; use clap::Parser; use console::style; use dialoguer::Confirm; @@ -265,11 +264,15 @@ fn main() -> Result<(), Box> { } }; } - SubCommand::Check { file, list } => { + SubCommand::Check { + file, + list, + password, + } => { if list { print_checks(); } else { - let notices = check(Path::new(file.as_str())); + let notices = check_file(Path::new(file.as_str()), password); println!( "Es wurden {} Probleme gefunden\n", notices