use log::error;
use serde_json::map::Map;
use serde_json::Value;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use std::str::FromStr;
#[derive(Debug, Default)]
pub(crate) struct Evil {
pub certs: HashMap<String, String>,
pub thread_names: HashMap<u32, String>,
}
pub(crate) fn handle_evil(evil_path: &Path) -> Option<Evil> {
let evil_json = File::open(evil_path)
.map_err(|e| {
error!("Could not load Extra JSON at {:?}", evil_path);
e
})
.ok()?;
let buf = BufReader::new(evil_json);
let mut json: Map<String, Value> = serde_json::from_reader(buf)
.map_err(|e| {
error!("Could not parse Extra JSON (was not valid JSON)");
e
})
.ok()?;
fn evil_obj<K, V>(json: &mut Map<String, Value>, field_name: &str) -> Option<HashMap<K, V>>
where
K: for<'de> serde::de::Deserialize<'de> + Eq + std::hash::Hash,
V: for<'de> serde::de::Deserialize<'de>,
{
json.remove(field_name).and_then(|val| {
match val {
Value::Object(_) => serde_json::from_value(val).ok(),
Value::String(string) => serde_json::from_str(&string).ok(),
_ => None,
}
.or_else(|| {
error!("Could not parse Evil JSON's {} (not an object)", field_name);
None
})
})
}
let certs = evil_obj(&mut json, "ModuleSignatureInfo")
.map(|certs: HashMap<String, Vec<String>>| {
let mut cert_map = HashMap::new();
for (cert, modules) in certs {
for module in modules {
cert_map.insert(module, cert.clone());
}
}
cert_map
})
.unwrap_or_default();
let thread_names = json
.remove("ThreadIdNameMapping")
.unwrap_or_default()
.as_str()
.unwrap_or_default()
.split(',')
.filter_map(|entry| {
entry.split_once(":").and_then(|(key, val)| {
let key = u32::from_str(key).ok();
let val = val
.strip_prefix('"')
.and_then(|val| val.strip_suffix('"'))
.map(String::from);
key.zip(val)
})
})
.collect();
Some(Evil {
certs,
thread_names,
})
}