52 lines
2.6 KiB
Python
52 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""nc_compare.py — every file under Ödön's „Csalad" folder through Nextcloud's own WebDAV door (the box's LAN address with
|
|
the Host header; TLS not verified, the rehearsal's tester4.test has no DNS), sha256 against the rehearsal's A5 manifest.
|
|
Env: REHEARSAL_2026_10_20_ODON_PW (under `sec run`). Prints counts and up to 15 differing names; never a secret."""
|
|
import base64, hashlib, http.client, os, ssl, sys, unicodedata, urllib.parse, xml.etree.ElementTree as ET
|
|
IP, HOST = "192.168.0.139", "cloud.tester4.test"
|
|
MAN = "/mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/rehearsal-2026-10-20/A5-data/MANIFEST.tsv"
|
|
auth = "Basic " + base64.b64encode(("odon:" + os.environ["REHEARSAL_2026_10_20_ODON_PW"]).encode()).decode()
|
|
ctx = ssl._create_unverified_context()
|
|
def req(method, path, body=None, extra=None):
|
|
c = http.client.HTTPSConnection(IP, 443, context=ctx, timeout=300)
|
|
h = {"Host": HOST, "Authorization": auth}; h.update(extra or {})
|
|
c.request(method, path, body=body, headers=h); r = c.getresponse(); data = r.read(); c.close()
|
|
return r.status, data
|
|
base = "/remote.php/dav/files/odon"
|
|
files = {}
|
|
def walk(path):
|
|
st, data = req("PROPFIND", urllib.parse.quote(base + path), b'<?xml version="1.0"?><d:propfind xmlns:d="DAV:"><d:prop><d:resourcetype/></d:prop></d:propfind>', {"Depth": "1"})
|
|
if st != 207:
|
|
print("PROPFIND", path, st); return
|
|
for resp in ET.fromstring(data).findall("{DAV:}response"):
|
|
href = urllib.parse.unquote(resp.find("{DAV:}href").text)
|
|
rel = href[len(base):]
|
|
if rel.rstrip("/") == path.rstrip("/"):
|
|
continue
|
|
if resp.find(".//{DAV:}collection") is not None:
|
|
walk(rel)
|
|
else:
|
|
files[rel] = href
|
|
walk("/Csalad/")
|
|
want = {}
|
|
for line in open(MAN, encoding="utf-8"):
|
|
p = line.rstrip("\n").split("\t")
|
|
if p[0].startswith("nextcloud/Csalad/"):
|
|
want[unicodedata.normalize("NFC", "/" + p[0][len("nextcloud/"):])] = p[2]
|
|
same, differ, extra = 0, [], []
|
|
got = {}
|
|
for rel, href in files.items():
|
|
st, data = req("GET", urllib.parse.quote(href))
|
|
got[unicodedata.normalize("NFC", rel)] = hashlib.sha256(data).hexdigest() if st == 200 else f"HTTP{st}"
|
|
for k, h in want.items():
|
|
if got.get(k) == h:
|
|
same += 1
|
|
else:
|
|
differ.append(("MISSING" if k not in got else "DIFFERS") + " " + k)
|
|
extra = [k for k in got if k not in want]
|
|
print(f"nextcloud Csalad: manifest {len(want)} files; on the box {len(got)}; byte-identical {same}; missing/different {len(differ)}; extra {len(extra)}")
|
|
for d in differ[:15]:
|
|
print(" ", d)
|
|
for e in extra[:8]:
|
|
print(" EXTRA", e)
|