🔒 Repository is read-only – file editing is disabled.

PaganLinux/tmp-verify-content-diff.py main

109 linii Raw ← Powrót
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
#!/usr/bin/env python3
"""Rozstrzyga 14 przypadkow CONTENT_DIFF: czy https serwuje ten sam plik co http.

Dla kazdego wystapienia:
  - key == 'url' (strona domowa, nie jest pobierana przy buildzie) -> uznaj za OK
  - key == 'source':
      * jesli receptura ma realna sume dla tego zrodla -> pobierz https i porownaj sume
      * inaczej -> pobierz http i https, porownaj sha256 obu
Wynik: lista ZWERYFIKOWANYCH (mozna bezpiecznie podmienic) i ODRZUCONYCH.
"""
import hashlib
import json
import os
import re
import subprocess
import sys
import tempfile

import yaml

R = "/var/lib/pagan-sync/recipes"
PH = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}")

audit = json.load(open("/tmp/https-audit.json"))
entries = audit.get("CONTENT_DIFF", [])


def as_list(v):
    if v is None:
        return []
    return v if isinstance(v, list) else [v]


def expand(s, d):
    def rep(m):
        k = m.group(1)
        return str(d[k]) if k in d and not isinstance(d[k], (dict, list)) else m.group(0)
    return PH.sub(rep, s)


def fetch_sha(url):
    """Pobiera URL do temp i zwraca sha256 (lub None)."""
    fd, path = tempfile.mkstemp(prefix="pagvd-")
    os.close(fd)
    try:
        p = subprocess.run(["curl", "-sS", "-L", "--max-time", "300", "-o", path, "-w",
                            "%{http_code}", "-A", "curl/8.7.1", url],
                           capture_output=True, text=True)
        code = (p.stdout or "").strip()
        if code != "200":
            return None, f"HTTP {code}"
        h = hashlib.sha256()
        with open(path, "rb") as f:
            for chunk in iter(lambda: f.read(1 << 20), b""):
                h.update(chunk)
        return h.hexdigest(), "ok"
    finally:
        try:
            os.unlink(path)
        except OSError:
            pass


verified, rejected = [], []
for e in entries:
    rel, key, raw, exp = e["recipe"], e["key"], e["raw"], e["expanded"]
    d = yaml.safe_load(open(f"{R}/{rel}", newline="", encoding="utf-8")) or {}
    if key == "url":
        verified.append((rel, key, raw, "strona domowa - https dziala"))
        continue

    srcs = as_list(d.get("source"))
    sums = as_list(d.get("sha256sums"))
    try:
        idx = [str(s) for s in srcs].index(raw)
    except ValueError:
        rejected.append((rel, key, raw, "nie znaleziono w source"))
        continue
    recorded = str(sums[idx]) if idx < len(sums) else None
    https_url = "https://" + expand(raw, d)[len("http://"):]

    if recorded and not recorded.strip().upper().startswith("SKIP"):
        got, note = fetch_sha(https_url)
        if got == recorded:
            verified.append((rel, key, raw, f"sha256 https == suma w recepturze ({note})"))
        else:
            rejected.append((rel, key, raw,
                             f"sha256 https={got} != suma w recepturze={recorded} ({note})"))
    else:
        http_url = expand(raw, d)
        h1, n1 = fetch_sha(http_url)
        h2, n2 = fetch_sha(https_url)
        if h1 and h2 and h1 == h2:
            verified.append((rel, key, raw, f"sha256 http == https ({n1}/{n2})"))
        else:
            rejected.append((rel, key, raw, f"http={h1}({n1}) https={h2}({n2})"))

print(f"ZWERYFIKOWANE ({len(verified)}):")
for v in verified:
    print(f"   OK  {v[0]} [{v[1]}] {v[3]}")
print(f"\nODRZUCONE ({len(rejected)}):")
for v in rejected:
    print(f"   NIE {v[0]} [{v[1]}] {v[3]}")
    print(f"       {v[2][:100]}")

json.dump({"verified": verified, "rejected": rejected,
           "verified_urls": [v[2] for v in verified]},
          open("/tmp/content-diff-verdict.json", "w"), indent=1, ensure_ascii=False)
print("\nzapisano /tmp/content-diff-verdict.json")