#!/usr/bin/env python3 """Share — local file sharing server (HTTPS).""" import hashlib import json import ssl import sys import threading from pathlib import Path from cert import ensure_cert, get_local_ip from cleanup import cleanup_loop from config import BASE_DIR, SECS_PER_DAY, client_cfg, load_config from server import Handler, ShareServer def main(): if len(sys.argv) > 1 and sys.argv[1] == "hash": token = sys.argv[2] if len(sys.argv) > 2 else input("Token: ") print(hashlib.sha256(token.encode()).hexdigest()) return conf = load_config() port = int(conf["port"]) upload_dir = Path(conf["dir"]).expanduser().resolve() max_age = int(conf["ttl"]) * SECS_PER_DAY san_list = conf["san"].split() if conf["san"] else None upload_dir.mkdir(parents=True, exist_ok=True) threading.Thread(target=cleanup_loop, args=(upload_dir, max_age), daemon=True).start() ip = get_local_ip() cfg_tag = f"".encode() html = (BASE_DIR / "static" / "index.html").read_bytes() html = html.replace(b"", cfg_tag) if conf["cert"] and conf["key"]: cert, key = Path(conf["cert"]), Path(conf["key"]) else: cert_dir = BASE_DIR / ".certs" cert, key = ensure_cert(cert_dir, extra_ips=san_list) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ctx.load_cert_chain(cert, key) token = conf["token"] if not token: print("\n WARNING: no token set — anyone on the network has full access.") print(" Set `token` in share.config (see SETUP.md) or pass --token.") # If token looks like a SHA-256 hash, pass it as pre-hashed is_hash = len(token) == 64 and all(c in "0123456789abcdef" for c in token) server = ShareServer(("0.0.0.0", port), Handler, upload_dir=upload_dir, html=html, ssl_ctx=ctx, token=token, token_is_hash=is_hash) print("\n Share running") print(f" Local: https://localhost:{port}") print(f" Network: https://{ip}:{port}") print(f" Files: {upload_dir}\n") try: server.serve_forever() except KeyboardInterrupt: print("\n Stopped.") server.server_close() if __name__ == "__main__": main()