night evidence: both Nextcloud upload trees 3031/3033 byte-identical against the night manifest (the 2 missing are the uploader's by-design skips)
gates / gates (push) Successful in 15m49s
gates / gates (push) Successful in 15m49s
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
nextcloud Csalad_feltoltes: manifest 3033 files; on the box 3031; byte-identical 3031; missing/different 2; extra 0
|
||||
MISSING /Csalad_feltoltes/nagy_fajl_1_5GB.bin
|
||||
MISSING /Csalad_feltoltes/Kulonleges_nevek/link_a_nagy_fajlra
|
||||
nextcloud Csalad_proof1: manifest 3033 files; on the box 3031; byte-identical 3031; missing/different 2; extra 0
|
||||
MISSING /Csalad_proof1/nagy_fajl_1_5GB.bin
|
||||
MISSING /Csalad_proof1/Kulonleges_nevek/link_a_nagy_fajlra
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
"""nc_compare.py (night 2026-10-21 copy: folder as argv[1], the night manifest) — 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
|
||||
import sys
|
||||
IP, HOST = "192.168.0.125", "cloud.tester4.test"
|
||||
FOLDER = sys.argv[1] # night 2026-10-21: the uploaded folder (Csalad_feltoltes / Csalad_proof1)
|
||||
MAN = "/mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/night-2026-10-21/P1-soak/05-MANIFEST-night.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("/" + FOLDER + "/")
|
||||
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", "/" + FOLDER + p[0][len("nextcloud/Csalad"):])] = 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 {FOLDER}: 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)
|
||||
Reference in New Issue
Block a user