From 39ee661dc7980fce4262b08f05a28eac9c503983 Mon Sep 17 00:00:00 2001 From: Jia Chao Date: Fri, 14 Jun 2024 10:58:15 +0800 Subject: [PATCH] release 0.1.0 Signed-off-by: Jia Chao --- src/lib.rs | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/test.rs | 24 ++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 src/test.rs diff --git a/src/lib.rs b/src/lib.rs index 9922e78..100b2b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,48 @@ +use std::fs::File; +use std::io; + use cvrf_xmlparser::{Severity, XmlReader}; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; +use tracing::{debug, error, instrument, trace}; +use xml::reader::XmlEvent; + +#[cfg(test)] +mod test; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateInfoDb { db: Vec, } +impl UpdateInfoDb { + pub fn new() -> Self { + UpdateInfoDb { db: Vec::new() } + } + + #[instrument(skip(self))] + pub fn load_xml(&mut self, xmlfile: &str) -> io::Result<()> { + let file = File::open(xmlfile)?; + let mut source = XmlReader::new(file); + let xmlreader = &mut source; + + loop { + let event = xmlreader.next(); + if xmlreader.depth() != 2 { + if event == Ok(XmlEvent::EndDocument) { + trace!("End of the xml, break..."); + break; + } + continue; + } + + let mut updateinfo = UpdateInfo::new(); + updateinfo.load_from_xml(xmlreader); + self.db.push(updateinfo); + } + Ok(()) + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateInfo { // sa id @@ -33,6 +70,111 @@ pub struct UpdateInfo { pkglist: Vec, } +impl UpdateInfo { + pub fn new() -> Self { + UpdateInfo { + id: String::new(), + title: String::new(), + severity: Severity::new(), + release: String::new(), + //date: String::new(), + cves: Vec::new(), + description: String::new(), + pkglist: Vec::new(), + } + } + + #[instrument(skip(self, xmlreader))] + fn load_from_xml(&mut self, xmlreader: &mut XmlReader) { + loop { + let key = if let Some(key) = xmlreader.next_start_name_under_depth(1) { + key + } else { + break; + }; + + debug!("Parser {key} content"); + match key.as_str() { + "id" => self.id = xmlreader.next_characters(), + "title" => self.title = xmlreader.next_characters(), + "severity" => { + self.severity = xmlreader.next_characters().parse::().unwrap() + } + "release" => self.release = xmlreader.next_characters(), + "description" => self.description = xmlreader.next_characters(), + "references" => self.handle_references(xmlreader), + "pkglist" => self.handle_pkglist(xmlreader), + _ => {} + } + } + } + + #[instrument(skip(self, xmlreader))] + fn handle_references(&mut self, xmlreader: &mut XmlReader) { + loop { + if xmlreader.depth() < 3 { + break; + } + match xmlreader.next() { + Ok(XmlEvent::StartElement { attributes, .. }) => { + for attr in attributes { + match attr.name.local_name.as_str() { + "id" => self.cves.push(attr.value.clone()), + _ => {} + } + } + } + Err(e) => { + error!("XmlReader Error: {e}"); + break; + } + _ => {} + } + } + } + + #[instrument(skip(self, xmlreader))] + fn handle_pkglist(&mut self, xmlreader: &mut XmlReader) { + loop { + if xmlreader.depth() < 3 { + break; + } + match xmlreader.next() { + Ok(XmlEvent::StartElement { + name, attributes, .. + }) => { + if name.local_name.as_str() != "package" { + continue; + } + let mut rpminfo = RpmInfo::new(); + + for attr in attributes { + rpminfo.set(attr.name.local_name.as_str(), attr.value.clone()); + /* + match attr.name.local_name.as_str() { + "name" => rpminfo.name = attr.value.clone(), + "epoch" => rpminfo.epoch = attr.value.clone(), + "version" => rpminfo.version = attr.value.clone(), + "release" => rpminfo.release = attr.value.clone(), + "arch" => rpminfo.arch = attr.value.clone(), + _ => {} + } + */ + } + + rpminfo.set("file", xmlreader.next_characters()); + self.pkglist.push(rpminfo); + } + Err(e) => { + error!("XmlReader Error: {e}"); + break; + } + _ => {} + } + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RpmInfo { // 包名 @@ -61,6 +203,19 @@ impl RpmInfo { } } + #[instrument(skip(self))] + pub fn set(&mut self, key: &str, value: String) { + match key { + "name" => self.name = value, + "epoch" => self.epoch = value, + "version" => self.version = value, + "release" => self.release = value, + "arch" => self.arch = value, + "file" => self.file = value, + _ => error!("Unknow field: {key}"), + } + } + pub fn name(&self) -> &str { &self.name } diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..c566cc8 --- /dev/null +++ b/src/test.rs @@ -0,0 +1,24 @@ +use crate::*; + +#[test] +fn it_works() { + let updatexml = "test/updateinfo.xml"; + + let mut db = UpdateInfoDb::new(); + db.load_xml(&updatexml).unwrap(); + + let id = "openEuler-SA-2022-1587"; + let title = "An update for mariadb is now available for openEuler-22.03-LTS"; + let severity = cvrf_xmlparser::Severity::Important; + let release = "openEuler"; + let cves = 10; + + let updateinfo = &db.db[0]; + assert_eq!(updateinfo.id, id); + assert_eq!(updateinfo.title, title); + assert_eq!(updateinfo.severity, severity); + assert_eq!(updateinfo.release, release); + assert_eq!(updateinfo.cves.len(), cves); + + assert!(true); +}