Export-Metadaten: category_labels JSON-robust parsen, Keyword-Sanitizer
- category_labels ist in der DB ein JSON-Dict (primary/secondary/tertiary/
mentioned), nicht ein Komma-String. Der bisherige split(",") fuehrte dazu,
dass ein nacktes { als Keyword durchrutschte. WeasyPrint bricht den
PDF-Keywords-Stream an dieser Stelle ab, weil { in PDF-Syntax eine
Sonderbedeutung hat — Ergebnis war "OSINT, Live-Monitoring, AegisSight, {".
- Neuer Parser: erst JSON (Dict oder Liste), Fallback auf Komma-String.
- _sanitize_keyword(): filtert {, }, [, ], Backslash und normalisiert
Whitespace in allen Keywords (Defense in Depth).
Dieser Commit ist enthalten in:
@@ -451,24 +451,49 @@ def _build_export_metadata(
|
|||||||
if organization_name:
|
if organization_name:
|
||||||
keywords.append(organization_name)
|
keywords.append(organization_name)
|
||||||
|
|
||||||
# category_labels ist ein Komma-getrennter String
|
# category_labels: kann JSON-Dict (Karte primary/secondary/...), JSON-Liste
|
||||||
cat_labels = incident.get("category_labels") or ""
|
# oder ein Komma-getrennter String sein. Nur die Label-Werte extrahieren.
|
||||||
for lbl in cat_labels.split(","):
|
cat_labels_raw = (incident.get("category_labels") or "").strip()
|
||||||
lbl = lbl.strip()
|
if cat_labels_raw:
|
||||||
if lbl:
|
cat_values: list[str] = []
|
||||||
|
try:
|
||||||
|
parsed = json.loads(cat_labels_raw)
|
||||||
|
if isinstance(parsed, dict):
|
||||||
|
cat_values = [str(v).strip() for v in parsed.values() if isinstance(v, str) and v.strip()]
|
||||||
|
elif isinstance(parsed, list):
|
||||||
|
cat_values = [str(v).strip() for v in parsed if isinstance(v, str) and v.strip()]
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
cat_values = [lbl.strip() for lbl in cat_labels_raw.split(",") if lbl.strip()]
|
||||||
|
# Keine JSON-Fragmente (geschweifte/eckige Klammern) als Keyword zulassen
|
||||||
|
for lbl in cat_values:
|
||||||
|
if lbl and not any(c in lbl for c in "{}[]"):
|
||||||
keywords.append(lbl)
|
keywords.append(lbl)
|
||||||
|
|
||||||
if top_locations:
|
if top_locations:
|
||||||
keywords.extend([loc for loc in top_locations if loc])
|
keywords.extend([loc for loc in top_locations if loc])
|
||||||
|
|
||||||
|
# Sanitize: Zeilenumbrueche/Tabs weg, Sonderzeichen mit PDF-Sonderbedeutung filtern
|
||||||
|
def _sanitize_keyword(kw: str) -> str:
|
||||||
|
if not kw:
|
||||||
|
return ""
|
||||||
|
# Whitespace normalisieren
|
||||||
|
cleaned = re.sub(r"\s+", " ", kw).strip()
|
||||||
|
# PDF-Dict/Array-Klammern und Backslash raus (WeasyPrint escaped () bei Strings,
|
||||||
|
# { und [ koennen aber den Keywords-Stream abschneiden)
|
||||||
|
cleaned = re.sub(r"[{}\[\]\\]", "", cleaned)
|
||||||
|
return cleaned.strip(" ,;:")
|
||||||
|
|
||||||
# Dedup (case-insensitive) mit Reihenfolge erhalten, max 15
|
# Dedup (case-insensitive) mit Reihenfolge erhalten, max 15
|
||||||
seen = set()
|
seen = set()
|
||||||
unique_keywords: list[str] = []
|
unique_keywords: list[str] = []
|
||||||
for kw in keywords:
|
for kw in keywords:
|
||||||
key = kw.lower()
|
clean_kw = _sanitize_keyword(kw)
|
||||||
|
if not clean_kw:
|
||||||
|
continue
|
||||||
|
key = clean_kw.lower()
|
||||||
if key not in seen:
|
if key not in seen:
|
||||||
seen.add(key)
|
seen.add(key)
|
||||||
unique_keywords.append(kw)
|
unique_keywords.append(clean_kw)
|
||||||
if len(unique_keywords) >= 15:
|
if len(unique_keywords) >= 15:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren