#!/usr/bin/env python3
"""Download source chunks and verify them, without extracting or executing sources."""
from pathlib import Path
from urllib.request import urlopen
from urllib.parse import urljoin,urlsplit
import hashlib,json,sys

def recover(base,folder):
    base=base.rstrip('/')+'/'
    if urlsplit(base).scheme not in ('https','http'):raise ValueError('Adresse HTTP(S) attendue.')
    with urlopen(urljoin(base,'sources-manifest.json'),timeout=60) as response:m=json.load(response)
    name=m['output_file']
    if Path(name).name!=name:raise ValueError('Nom de fichier invalide.')
    target=folder/name;temporary=folder/(name+'.partial')
    if target.exists() or temporary.exists():raise FileExistsError('Le fichier final ou temporaire existe déjà. Choisir un dossier vide ou renommer le fichier existant.')
    complete=hashlib.sha256();total=0
    try:
        with temporary.open('xb') as output:
            for index,part in enumerate(m['parts'],1):
                relative=part['file'];p=Path(relative)
                if p.is_absolute() or '..' in p.parts or not relative.startswith('downloads/'):raise ValueError('Chemin de partie invalide.')
                print(f"Téléchargement {index}/{len(m['parts'])}",flush=True)
                digest=hashlib.sha256();count=0
                with urlopen(urljoin(base,relative),timeout=120) as response:
                    for block in iter(lambda:response.read(1024*1024),b''):
                        digest.update(block);complete.update(block);output.write(block);count+=len(block)
                if count!=part['size'] or digest.hexdigest()!=part['sha256']:raise ValueError('Partie endommagée : '+relative)
                total+=count
        if total!=m['size'] or complete.hexdigest()!=m['sha256']:raise ValueError('Empreinte globale incorrecte.')
        temporary.rename(target);print('Sources vérifiées :',target)
    except BaseException:
        temporary.unlink(missing_ok=True)
        raise
    return target

if __name__=='__main__':
    if len(sys.argv)!=2:raise SystemExit('Usage : python3 Recuperer-sources.py https://adresse-du-site-sources/')
    recover(sys.argv[1],Path.cwd())
