use std::collections::HashMap; use cvrf_xmlparser::{SaInfo, CVE}; use serde::{Deserialize, Serialize}; use updateinfo_xmlparser::{UpdateInfoDb, RpmInfo}; // PackageDb 从 updateinfo 中获取 // 以包名为键,值为一个 Vector ,里面包含更新的不同版本的 rpm 包信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PackgeDb { db: HashMap>, } impl PackgeDb { pub fn new() -> Self { PackgeDb { db: HashMap::new(), } } /// 从已有的 updateinfo 仓库文件中,获取所有与安全更新相关的软件包 pub fn load_from_updateinfodb(&mut self, updateinfodb: &UpdateInfoDb) { for updateinfo in &updateinfodb.db { for pkg in &updateinfo.pkglist { if let Some(rpms) = self.db.get_mut(pkg.name()) { rpms.push(pkg.clone()); } else { let rpms = vec![pkg.clone()]; self.db.insert(pkg.name().to_string(), rpms); } } } } pub fn db(&self) -> &HashMap> { &self.db } } // SaDb 为精简版的安全公告集 // 一般从安全公告相关的 xml 文件解析、转换而来 // 目前支持 cvrf 格式 // 其键为 SA id,值为详情 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SaDb { db: HashMap, } impl SaDb { pub fn new() -> Self { SaDb { db: HashMap::new(), } } /// 一般来自对 cvrf 文件解析并转换为 SaInfo 的文本数据文件 pub fn load_from_file(&mut self, file: &str) -> crate::Result<()> { let data = std::fs::read_to_string(file)?; self.db = toml::from_str(&data)?; Ok(()) } /// 从 SaInfo 中提取出所有的 CVE 源 pub fn get_cvedb(&self) -> CveDb { let mut cvedb = CveDb::new(); self.db.iter().for_each(|(_, sainfo)| { sainfo.cves.iter().for_each(|cve| { cvedb.db.insert(cve.id.clone(), cve.clone()); }) }); cvedb } } // CveDb 中的 CVE,以 cve_id -> cve_info 形式存储 // 目前的来源为 cvrf 文件,SaDb #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CveDb { db: HashMap, } impl CveDb { #[allow(dead_code)] pub fn new() -> Self { CveDb { db: HashMap::new(), } } } #[cfg(test)] mod test { use super::*; #[test] fn pkgdb_works() { assert!(true); let updatexml = "test/updateinfo.xml"; let mut updatedb = UpdateInfoDb::new(); updatedb.load_xml(&updatexml).unwrap(); let mut pkgdb = PackgeDb::new(); pkgdb.load_from_updateinfodb(&updatedb); let bash_pkgs = pkgdb.db.get("bash").unwrap(); assert_eq!(bash_pkgs.len(), 2); } }