"""Fetch immutable official-source inputs; hash before extraction; never execute."""
from pathlib import Path
import urllib.request,json,hashlib,tarfile,posixpath
base=Path(__file__).parent;cache=base/'inputs';cache.mkdir(exist_ok=True)
commit=json.loads((base/'upstream-commit.json').read_text())['commit']
items=[{'name':'zeroperl-source.tar.gz','url':f'https://codeload.github.com/6over3/zeroperl/tar.gz/{commit}'},
 {'name':'perl-5.42.0.tar.gz','url':'https://www.cpan.org/src/5.0/perl-5.42.0.tar.gz'},
 {'name':'exiftool-13.42.tar.gz','url':'https://codeload.github.com/exiftool/exiftool/tar.gz/refs/tags/13.42'},
 {'name':'zlib-1.3.1.tar.gz','url':'https://zlib.net/fossils/zlib-1.3.1.tar.gz'},
 {'name':'bzip2-1.0.8.tar.gz','url':'https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz'}]
for release in json.loads((base/'toolchain-release-metadata.json').read_text()).values():
 for a in release['assets']:items.append({'name':a['name'],'url':a['url'],'expected_sha256':a['digest'].split(':')[1]})
receipts=[]
for item in items:
 path=cache/item['name'];temporary=cache/(item['name']+'.partial')
 if not path.exists():
  req=urllib.request.Request(item['url'],headers={'User-Agent':'bounded-photo-feasibility'})
  with urllib.request.urlopen(req,timeout=60) as response,temporary.open('wb') as output:
   while chunk:=response.read(1024*1024):output.write(chunk)
  temporary.rename(path)
 digest=hashlib.file_digest(path.open('rb'),'sha256').hexdigest()
 if item.get('expected_sha256') and digest!=item['expected_sha256']:raise ValueError('release digest mismatch '+item['name'])
 with tarfile.open(path,'r:gz') as archive:
  for m in archive.getmembers():
   name=posixpath.normpath(m.name)
   if name.startswith('/') or name=='..' or name.startswith('../') or m.isdev() or m.isfifo():raise ValueError('unsafe member '+m.name)
   if m.issym() or m.islnk():
    target=posixpath.normpath(posixpath.join(posixpath.dirname(name),m.linkname) if m.issym() else m.linkname)
    if target.startswith('/') or target=='..' or target.startswith('../'):raise ValueError('escaping link '+m.name)
 receipts.append({**item,'bytes':path.stat().st_size,'sha256':digest});(base/'input-lock.json').write_text(json.dumps(receipts,indent=2)+'\n');print(item['name'],path.stat().st_size,digest,flush=True)
