#!/usr/bin/env bash
# BigBrother Operator Script — Extract Print Jobs from PCAPs
#
# Reconstructs print jobs from TCP/9100 (JetDirect/RAW) traffic captured
# in PCAPs. Converts PCL/PostScript to PDF using Ghostscript.
#
# Print traffic is often unencrypted and contains sensitive documents:
# HR letters, financial reports, legal docs, network diagrams, etc.
#
# Usage: ./extract_print_jobs.sh <pcap_dir> [output_dir]
#
# Requires: tshark, ghostscript (gs)

set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

# ---------------------------------------------------------------------------
# Arguments
# ---------------------------------------------------------------------------

PCAP_DIR="${1:-}"
OUTPUT_DIR="${2:-$(pwd)/print-jobs-$(date +%Y%m%d-%H%M%S)}"

if [[ -z "$PCAP_DIR" ]]; then
    echo -e "${RED}Usage: $0 <pcap_dir> [output_dir]${NC}"
    exit 1
fi

if [[ ! -d "$PCAP_DIR" ]]; then
    echo -e "${RED}[-] PCAP directory not found: $PCAP_DIR${NC}"
    exit 1
fi

# Check dependencies
for tool in tshark gs; do
    if ! command -v "$tool" &>/dev/null; then
        echo -e "${RED}[-] $tool not found${NC}"
        case "$tool" in
            tshark) echo "    Install with: apt install tshark" ;;
            gs) echo "    Install with: apt install ghostscript" ;;
        esac
        exit 1
    fi
done

mkdir -p "$OUTPUT_DIR"/{raw,pdf,metadata}

echo -e "${CYAN}[*] BigBrother Print Job Extraction${NC}"
echo -e "    PCAP dir:  ${PCAP_DIR}"
echo -e "    Output:    ${OUTPUT_DIR}"
echo ""

# ---------------------------------------------------------------------------
# Extract print streams from PCAPs
# ---------------------------------------------------------------------------

JOB_COUNT=0
PDF_COUNT=0

for pcap in "$PCAP_DIR"/*.pcap "$PCAP_DIR"/*.pcapng; do
    [[ -f "$pcap" ]] || continue
    basename_pcap=$(basename "$pcap")
    echo -e "${YELLOW}[*] Scanning: ${basename_pcap}${NC}"

    # Check if this PCAP has any port 9100 traffic
    has_print=$(tshark -r "$pcap" -Y "tcp.port == 9100" -c 1 2>/dev/null | wc -l)
    if [[ "$has_print" -eq 0 ]]; then
        echo -e "    (no print traffic)"
        continue
    fi

    # Extract TCP streams on port 9100
    # Get unique stream indices for print traffic
    streams=$(tshark -r "$pcap" -Y "tcp.dstport == 9100 && tcp.len > 0" \
        -T fields -e tcp.stream 2>/dev/null | sort -un)

    for stream_id in $streams; do
        JOB_COUNT=$((JOB_COUNT + 1))
        raw_file="$OUTPUT_DIR/raw/job_${JOB_COUNT}_stream${stream_id}.raw"
        pdf_file="$OUTPUT_DIR/pdf/job_${JOB_COUNT}_stream${stream_id}.pdf"
        meta_file="$OUTPUT_DIR/metadata/job_${JOB_COUNT}.txt"

        # Extract the raw print data from the TCP stream
        tshark -r "$pcap" -q -z "follow,tcp,raw,${stream_id}" 2>/dev/null | \
            grep -E '^[0-9a-fA-F]+$' | xxd -r -p > "$raw_file" 2>/dev/null || true

        if [[ ! -s "$raw_file" ]]; then
            rm -f "$raw_file"
            JOB_COUNT=$((JOB_COUNT - 1))
            continue
        fi

        file_size=$(stat -c %s "$raw_file" 2>/dev/null || echo 0)
        echo -e "    Stream $stream_id: ${file_size} bytes"

        # Record metadata (source/dest IPs, timestamps)
        tshark -r "$pcap" -Y "tcp.stream == ${stream_id}" -c 1 \
            -T fields -e ip.src -e ip.dst -e frame.time 2>/dev/null > "$meta_file" || true
        echo "Raw file: $raw_file" >> "$meta_file"
        echo "Size: $file_size bytes" >> "$meta_file"

        # Detect format and convert to PDF
        file_magic=$(head -c 20 "$raw_file" | cat -v 2>/dev/null || echo "")

        if echo "$file_magic" | grep -q "%!PS\|%PDF\|^-E"; then
            # PostScript or PDF — convert with Ghostscript
            gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$pdf_file" \
                "$raw_file" 2>/dev/null && {
                PDF_COUNT=$((PDF_COUNT + 1))
                echo -e "    ${GREEN}Converted to PDF: $(basename $pdf_file)${NC}"
            } || {
                echo -e "    ${RED}Ghostscript conversion failed${NC}"
            }
        elif echo "$file_magic" | grep -qi "^.E.*HP\|PCL\|PJL"; then
            # PCL/PJL — try Ghostscript PCL interpreter
            gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile="$pdf_file" \
                "$raw_file" 2>/dev/null && {
                PDF_COUNT=$((PDF_COUNT + 1))
                echo -e "    ${GREEN}Converted PCL to PDF: $(basename $pdf_file)${NC}"
            } || {
                echo -e "    ${YELLOW}PCL conversion failed (raw data preserved)${NC}"
            }
        else
            echo -e "    ${YELLOW}Unknown format — raw data preserved${NC}"
            echo "Format: unknown (magic: $(head -c 10 "$raw_file" | xxd -p 2>/dev/null))" >> "$meta_file"
        fi
    done
done

# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------

echo ""
echo -e "${GREEN}[+] Print job extraction complete${NC}"
echo -e "    Print jobs found:  ${JOB_COUNT}"
echo -e "    Converted to PDF:  ${PDF_COUNT}"
echo ""

if [[ $JOB_COUNT -gt 0 ]]; then
    echo -e "${CYAN}[*] Output:${NC}"
    echo "    Raw data: $OUTPUT_DIR/raw/"
    echo "    PDFs:     $OUTPUT_DIR/pdf/"
    echo "    Metadata: $OUTPUT_DIR/metadata/"
    echo ""
    ls -lhS "$OUTPUT_DIR/pdf/" 2>/dev/null | tail -20 | sed 's/^/    /'
fi
