diff --git a/bin/web/src/lib/analysis.svelte.ts b/bin/web/src/lib/analysis.svelte.ts index 24889cb..f402a12 100644 --- a/bin/web/src/lib/analysis.svelte.ts +++ b/bin/web/src/lib/analysis.svelte.ts @@ -8,6 +8,13 @@ export type AnalysisReport = { export type ReportMetadata = { analyzers: AnalyzerMetadata[]; + rayhunter: RayhunterMetadata; +}; + +export type RayhunterMetadata = { + rayhunter_version: string; + system_os: string; + arch: string; }; export type AnalyzerMetadata = { diff --git a/bin/web/src/lib/components/AnalysisStatus.svelte b/bin/web/src/lib/components/AnalysisStatus.svelte index 86ea7d0..99cbd0e 100644 --- a/bin/web/src/lib/components/AnalysisStatus.svelte +++ b/bin/web/src/lib/components/AnalysisStatus.svelte @@ -2,8 +2,9 @@ import { AnalysisStatus } from "$lib/analysisManager.svelte"; import { EventType } from "$lib/analysis.svelte"; import type { ManifestEntry } from "$lib/manifest.svelte"; - let { entry }: { + let { entry, onclick }: { entry: ManifestEntry, + onclick: () => void, } = $props(); let summary = $derived.by(() => { @@ -32,12 +33,20 @@ } else { return 'Loading...'; } + }); + + let ready = $derived.by(() => { + let finished = entry.analysis_status === AnalysisStatus.Finished; + let report_available = entry.analysis_report !== undefined; + return finished && report_available; }) + + let button_class = $derived(ready ? "text-blue-400 underline" : ''); -

+ diff --git a/bin/web/src/lib/components/AnalysisTable.svelte b/bin/web/src/lib/components/AnalysisTable.svelte new file mode 100644 index 0000000..441bc9a --- /dev/null +++ b/bin/web/src/lib/components/AnalysisTable.svelte @@ -0,0 +1,41 @@ + + +

Warnings

+ + + + + + + + + + {#each report.rows as row, row_idx} + {#each row.analysis as analysis} + {@const parsed_date = new Date(analysis.timestamp)} + {@const warnings = analysis.events.filter(e => e.type === EventType.Warning)} + {#each warnings as warning} + {@const severity = ['Low', 'Medium', 'High'][warning.severity]} + {@const severity_class = ['bg-red-200', 'bg-red-400', 'bg-red-600'][warning.severity]} + + + + + + {/each} + {/each} + {/each} + +
TimestampWarningSeverity
{date_formatter.format(parsed_date)}{warning.message}{severity}
diff --git a/bin/web/src/lib/components/AnalysisView.svelte b/bin/web/src/lib/components/AnalysisView.svelte new file mode 100644 index 0000000..2bda260 --- /dev/null +++ b/bin/web/src/lib/components/AnalysisView.svelte @@ -0,0 +1,40 @@ + + +
+ {#if entry.analysis_report === undefined} +

Report unavailable, try refreshing.

+ {:else if typeof(entry.analysis_report) === 'string'} +

Error getting analysis report: {entry.analysis_report}

+ {:else} + {@const metadata: ReportMetadata = entry.analysis_report.metadata} +
+ {#if entry.analysis_report.rows.length > 0} + + {:else} +

No warnings to display!

+ {/if} +
+

Metadata

+

Rayhunter version: {metadata.rayhunter.rayhunter_version}

+

Device system OS: {metadata.rayhunter.system_os}

+

Analyzers

+ {#each metadata.analyzers as analyzer} +

{analyzer.name}: {analyzer.description}

+ {/each} +
+
+ {/if} +
diff --git a/bin/web/src/lib/components/ManifestTable.svelte b/bin/web/src/lib/components/ManifestTable.svelte index 9377942..08032c5 100644 --- a/bin/web/src/lib/components/ManifestTable.svelte +++ b/bin/web/src/lib/components/ManifestTable.svelte @@ -8,7 +8,7 @@ let { entries, current_entry }: Props = $props(); - +
@@ -17,16 +17,16 @@ - + {#if current_entry !== undefined} - + {/if} - {#each entries as entry} - + {#each entries as entry, i} + {/each}
NameSize (bytes) PCAP QMDLAnalysis ResultAnalysis Delete
diff --git a/bin/web/src/lib/components/ManifestTableRow.svelte b/bin/web/src/lib/components/ManifestTableRow.svelte index f306199..47af51c 100644 --- a/bin/web/src/lib/components/ManifestTableRow.svelte +++ b/bin/web/src/lib/components/ManifestTableRow.svelte @@ -3,9 +3,11 @@ import DownloadLink from '$lib/components/DownloadLink.svelte'; import DeleteButton from "$lib/components/DeleteButton.svelte"; import AnalysisStatus from "./AnalysisStatus.svelte"; - let { entry, current }: { + import AnalysisView from "./AnalysisView.svelte"; + let { entry, current, i }: { entry: ManifestEntry; current: boolean; + i: number } = $props(); // passing `undefined` as the locale uses the browser default @@ -13,17 +15,19 @@ timeStyle: "long", dateStyle: "short", }); - let row_color = current ? "bg-green-300" : "even:bg-gray-100"; + let normal_row_color = i % 2 == 0 ? "bg-white" : "bg-gray-100"; + let row_color = current ? "bg-green-300" : normal_row_color; + let analysis_visible = $state(false); - + {entry.name} {date_formatter.format(entry.start_time)} {date_formatter.format(entry.last_message_time)} {entry.qmdl_size_bytes} - + { analysis_visible = !analysis_visible; }} entry={entry} /> {#if current} {:else} @@ -35,3 +39,9 @@ {/if} + + + + + + diff --git a/bin/web/src/routes/+page.svelte b/bin/web/src/routes/+page.svelte index f4da74a..798f175 100644 --- a/bin/web/src/routes/+page.svelte +++ b/bin/web/src/routes/+page.svelte @@ -33,8 +33,8 @@
{#if loaded} - + {:else}

Loading...

{/if} diff --git a/bin/web/src/routes/entry/[name]/+page.svelte b/bin/web/src/routes/entry/[name]/+page.svelte deleted file mode 100644 index e69de29..0000000