pub mod artifact;
pub mod challenge;
pub mod filesystem;
pub mod intel;
pub mod memory;
#[cfg(feature = "sqlite")]
pub mod sqlite;
pub mod state;
pub mod telemetry;
pub use artifact::ArtifactStorage;
pub use challenge::ChallengeStorage;
pub use intel::IntelStorage;
pub use state::StateStorage;
pub use telemetry::TelemetryStorage;
use std::time::SystemTime;
use url::Url;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArtifactKind {
ScreenshotViewport,
ScreenshotFullPage,
ScreenshotElement,
SnapshotHtml,
SnapshotDom,
SnapshotPostJsHtml,
SnapshotResponseBody,
SnapshotState,
SnapshotAxTree,
SnapshotRuntimeRoutes,
SnapshotNetworkEndpoints,
SnapshotIndexedDb,
SnapshotCacheStorage,
SnapshotManifest,
SnapshotServiceWorkers,
SnapshotPwaState,
}
impl ArtifactKind {
pub fn wire_str(&self) -> &'static str {
match self {
ArtifactKind::ScreenshotViewport => "screenshot.viewport",
ArtifactKind::ScreenshotFullPage => "screenshot.full_page",
ArtifactKind::ScreenshotElement => "screenshot.element",
ArtifactKind::SnapshotHtml => "snapshot.html",
ArtifactKind::SnapshotDom => "snapshot.dom_snapshot",
ArtifactKind::SnapshotPostJsHtml => "snapshot.post_js_html",
ArtifactKind::SnapshotResponseBody => "snapshot.response_body",
ArtifactKind::SnapshotState => "snapshot.state",
ArtifactKind::SnapshotAxTree => "snapshot.ax_tree",
ArtifactKind::SnapshotRuntimeRoutes => "snapshot.runtime_routes",
ArtifactKind::SnapshotNetworkEndpoints => "snapshot.network_endpoints",
ArtifactKind::SnapshotIndexedDb => "snapshot.indexeddb",
ArtifactKind::SnapshotCacheStorage => "snapshot.cache_storage",
ArtifactKind::SnapshotManifest => "snapshot.manifest",
ArtifactKind::SnapshotServiceWorkers => "snapshot.service_workers",
ArtifactKind::SnapshotPwaState => "snapshot.pwa_state",
}
}
pub fn mime(&self) -> &'static str {
match self {
ArtifactKind::ScreenshotViewport
| ArtifactKind::ScreenshotFullPage
| ArtifactKind::ScreenshotElement => "image/png",
ArtifactKind::SnapshotHtml
| ArtifactKind::SnapshotDom
| ArtifactKind::SnapshotPostJsHtml => "text/html",
ArtifactKind::SnapshotResponseBody => "application/octet-stream",
ArtifactKind::SnapshotState => "application/json",
ArtifactKind::SnapshotAxTree => "text/plain",
ArtifactKind::SnapshotRuntimeRoutes
| ArtifactKind::SnapshotNetworkEndpoints
| ArtifactKind::SnapshotIndexedDb
| ArtifactKind::SnapshotCacheStorage
| ArtifactKind::SnapshotManifest
| ArtifactKind::SnapshotServiceWorkers
| ArtifactKind::SnapshotPwaState => "application/json",
}
}
pub fn extension(&self) -> &'static str {
match self {
ArtifactKind::ScreenshotViewport
| ArtifactKind::ScreenshotFullPage
| ArtifactKind::ScreenshotElement => "png",
ArtifactKind::SnapshotHtml
| ArtifactKind::SnapshotDom
| ArtifactKind::SnapshotPostJsHtml => "html",
ArtifactKind::SnapshotResponseBody => "bin",
ArtifactKind::SnapshotState => "json",
ArtifactKind::SnapshotAxTree => "txt",
ArtifactKind::SnapshotRuntimeRoutes
| ArtifactKind::SnapshotNetworkEndpoints
| ArtifactKind::SnapshotIndexedDb
| ArtifactKind::SnapshotCacheStorage
| ArtifactKind::SnapshotManifest
| ArtifactKind::SnapshotServiceWorkers
| ArtifactKind::SnapshotPwaState => "json",
}
}
pub fn from_wire(s: &str) -> Option<Self> {
Some(match s {
"screenshot.viewport" => ArtifactKind::ScreenshotViewport,
"screenshot.full_page" => ArtifactKind::ScreenshotFullPage,
"screenshot.element" => ArtifactKind::ScreenshotElement,
"snapshot.html" => ArtifactKind::SnapshotHtml,
"snapshot.dom_snapshot" => ArtifactKind::SnapshotDom,
"snapshot.post_js_html" => ArtifactKind::SnapshotPostJsHtml,
"snapshot.response_body" => ArtifactKind::SnapshotResponseBody,
"snapshot.state" => ArtifactKind::SnapshotState,
"snapshot.ax_tree" => ArtifactKind::SnapshotAxTree,
"snapshot.runtime_routes" => ArtifactKind::SnapshotRuntimeRoutes,
"snapshot.network_endpoints" => ArtifactKind::SnapshotNetworkEndpoints,
"snapshot.indexeddb" => ArtifactKind::SnapshotIndexedDb,
"snapshot.cache_storage" => ArtifactKind::SnapshotCacheStorage,
"snapshot.manifest" => ArtifactKind::SnapshotManifest,
"snapshot.service_workers" => ArtifactKind::SnapshotServiceWorkers,
"snapshot.pwa_state" => ArtifactKind::SnapshotPwaState,
_ => return None,
})
}
}
#[derive(Debug, Clone)]
pub struct ArtifactMeta<'a> {
pub url: &'a Url,
pub final_url: Option<&'a Url>,
pub session_id: &'a str,
pub kind: ArtifactKind,
pub name: Option<&'a str>,
pub step_id: Option<&'a str>,
pub step_kind: Option<&'a str>,
pub selector: Option<&'a str>,
pub mime: Option<&'a str>,
}
#[derive(Debug, Clone)]
pub struct ArtifactRow {
pub id: i64,
pub url: Url,
pub final_url: Option<Url>,
pub session_id: String,
pub kind: ArtifactKind,
pub name: Option<String>,
pub step_id: Option<String>,
pub step_kind: Option<String>,
pub selector: Option<String>,
pub mime: String,
pub sha256: String,
pub size: u64,
pub created_at: SystemTime,
}
#[derive(Debug, Clone)]
pub struct PageMetadata {
pub final_url: Url,
pub status: u16,
pub bytes: u64,
pub rendered: bool,
pub kind: crate::discovery::AssetKind,
}
#[derive(Debug, Clone, Default)]
pub struct HostFacts {
pub favicon_mmh3: Option<i32>,
pub dns_json: Option<String>,
pub robots_present: Option<bool>,
pub manifest_present: Option<bool>,
pub service_worker_present: Option<bool>,
pub cert_sha256: Option<String>,
pub cert_subject_cn: Option<String>,
pub cert_issuer_cn: Option<String>,
pub cert_not_before: Option<String>,
pub cert_not_after: Option<String>,
pub cert_sans_json: Option<String>,
pub rdap_json: Option<String>,
pub registrar: Option<String>,
pub registrant_org: Option<String>,
pub registration_created: Option<String>,
pub registration_expires: Option<String>,
}
pub trait Storage:
ArtifactStorage + StateStorage + ChallengeStorage + TelemetryStorage + IntelStorage
{
fn as_any_ref(&self) -> Option<&dyn std::any::Any> {
None
}
}
pub(crate) fn session_id_for_url(url: &Url) -> String {
url.host_str()
.map(|h| format!("legacy:{h}"))
.unwrap_or_else(|| "legacy:unknown".to_string())
}