use std::collections::HashMap;
use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Technology {
pub name: String,
pub confidence: u8,
pub version: Option<String>,
pub categories: Vec<String>,
pub website: Option<String>,
pub description: Option<String>,
pub icon: Option<String>,
pub cpe: Option<String>,
pub saas: Option<bool>,
pub pricing: Option<Vec<String>>,
}
impl Technology {
pub fn from_name(name: String) -> Self {
Self {
name,
confidence: 50,
version: None,
categories: Vec::new(),
website: None,
description: None,
icon: None,
cpe: None,
saas: None,
pricing: None,
}
}
}
impl fmt::Display for Technology {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.version {
Some(v) if !v.is_empty() => write!(f, "{} {}", self.name, v),
_ => write!(f, "{}", self.name),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TechnologyLite {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
#[serde(default, skip_serializing_if = "is_default_confidence")]
pub confidence: u8,
}
impl TechnologyLite {
pub fn from_name(name: String) -> Self {
Self {
name,
version: None, confidence: 50, }
}
}
impl fmt::Display for TechnologyLite {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.version {
Some(v) if !v.is_empty() => write!(f, "{} {}", self.name, v),
_ => write!(f, "{}", self.name),
}
}
}
impl From<Technology> for TechnologyLite {
fn from(full: Technology) -> Self {
Self {
name: full.name,
version: full.version,
confidence: full.confidence,
}
}
}
fn is_default_confidence(conf: &u8) -> bool {
*conf == 100
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TechRule {
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub website: Option<String>,
#[serde(rename = "cats", default, alias = "categories")]
pub category_ids: Vec<u32>,
#[serde(default)]
pub icon: Option<String>,
#[serde(default)]
pub cpe: Option<String>,
#[serde(default)]
pub saas: Option<bool>,
#[serde(default)]
pub pricing: Option<Vec<String>>,
#[serde(default)]
pub url: Option<serde_json::Value>,
#[serde(default)]
pub html: Option<serde_json::Value>,
#[serde(default)]
pub script: Option<serde_json::Value>,
#[serde(default)]
pub script_src: Option<serde_json::Value>,
#[serde(default)]
pub meta: Option<HashMap<String, serde_json::Value>>,
#[serde(default)]
pub headers: Option<HashMap<String, serde_json::Value>>,
#[serde(default)]
pub implies: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CategoryRule {
#[serde(default)]
pub name: String,
#[serde(default)]
pub priority: Option<u32>,
#[serde(default)]
pub id: u32,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RuleLibrary {
pub tech_rules: HashMap<String, TechRule>,
pub category_rules: HashMap<String, CategoryRule>,
}