tshark protocol restriction lifted, frontedn details for packet
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 11s

This commit is contained in:
2026-03-08 16:54:28 +01:00
parent c41e68c0f3
commit 5ea4dd388e
3 changed files with 481 additions and 286 deletions

View File

@@ -1,5 +1,5 @@
// src/components/PacketViewer.tsx
import { DeleteOutlined, DownloadOutlined, SyncOutlined } from '@ant-design/icons';
import { DeleteOutlined, DownloadOutlined, EyeOutlined, SyncOutlined } from '@ant-design/icons';
import {
Button,
Card,
@@ -47,6 +47,15 @@ function base64ToBlob(b64: string) {
return new Blob([arr.buffer], { type: 'application/octet-stream' });
}
function formatJson(value: unknown) {
if (value == null) return '(no tshark data)';
try {
return JSON.stringify(value, null, 2);
} catch {
return '(failed to format tshark data)';
}
}
/**
* Improved deterministic color generation
*
@@ -133,6 +142,7 @@ export default function PacketViewer(): ReactElement {
const wsRef = useRef<WebSocket | null>(null);
const [hexModalOpen, setHexModalOpen] = useState(false);
const [rawHex, setRawHex] = useState<string | null>(null);
const [rawTshark, setRawTshark] = useState<string | null>(null);
const [rawB64ForDownload, setRawB64ForDownload] = useState<string | null>(null);
const [selectedPacket, setSelectedPacket] = useState<PacketRow | null>(null);
const queuedDuringPause = useRef<PacketRow[]>([]);
@@ -277,6 +287,7 @@ export default function PacketViewer(): ReactElement {
return;
}
setRawHex(base64ToHex(row.raw_b64));
setRawTshark(formatJson(row.dpi_metadata ?? null));
setRawB64ForDownload(row.raw_b64 ?? null);
setSelectedPacket(row);
setHexModalOpen(true);
@@ -457,28 +468,34 @@ export default function PacketViewer(): ReactElement {
{
title: 'Actions',
key: 'actions',
width: 180,
width: 96,
render: (_: any, rec: PacketRow) => (
<Space>
<Button size="small" onClick={() => openRawModal(rec)}>
View raw
</Button>
{rec.raw_b64 && (
<Tooltip title="View raw + tshark">
<Button
size="small"
icon={<DownloadOutlined />}
onClick={() => {
const blob = base64ToBlob(rec.raw_b64!);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `packet_${rec.id ?? 'pkt'}.bin`;
a.click();
URL.revokeObjectURL(url);
}}
>
Download
</Button>
icon={<EyeOutlined />}
onClick={() => openRawModal(rec)}
aria-label="View raw and tshark data"
/>
</Tooltip>
{rec.raw_b64 && (
<Tooltip title="Download raw">
<Button
size="small"
icon={<DownloadOutlined />}
onClick={() => {
const blob = base64ToBlob(rec.raw_b64!);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `packet_${rec.id ?? 'pkt'}.bin`;
a.click();
URL.revokeObjectURL(url);
}}
aria-label="Download raw packet"
/>
</Tooltip>
)}
</Space>
),
@@ -545,12 +562,22 @@ export default function PacketViewer(): ReactElement {
</Card>
<Modal
title={`Raw packet ${selectedPacket?.id ?? ''}`}
title={`Raw + tshark ${selectedPacket?.id ?? ''}`}
open={hexModalOpen}
onCancel={() => setHexModalOpen(false)}
onCancel={() => {
setHexModalOpen(false);
setRawTshark(null);
}}
footer={
<Space>
<Button onClick={() => setHexModalOpen(false)}>Close</Button>
<Button
onClick={() => {
setHexModalOpen(false);
setRawTshark(null);
}}
>
Close
</Button>
<Button icon={<DownloadOutlined />} onClick={downloadRaw} type="primary">
Download raw
</Button>
@@ -558,7 +585,16 @@ export default function PacketViewer(): ReactElement {
}
width={900}
>
<pre style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: 12 }}>{rawHex}</pre>
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
<div>
<Text strong>Raw bytes</Text>
<pre style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: 12, marginTop: 8 }}>{rawHex}</pre>
</div>
<div>
<Text strong>TShark data</Text>
<pre style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: 12, marginTop: 8 }}>{rawTshark}</pre>
</div>
</Space>
</Modal>
</div>
);