💾 Archived View for spartan.mozz.us › spartan_client.py captured on 2023-07-22 at 16:17:29.
⬅️ Previous capture (2021-11-30)
-=-=-=-=-=-=-
#!/usr/bin/env python3 """ A reference spartan:// protocol client. Copyright (c) Michael Lazar Blue Oak Model License 1.0.0 """ import argparse import shutil import socket import sys from urllib.parse import urlparse, unquote_to_bytes, quote_from_bytes def fetch_url(url, infile=None): url_parts = urlparse(url) if url_parts.scheme != "spartan": raise ValueError("Unrecognized URL scheme") host = url_parts.hostname port = url_parts.port or 300 path = url_parts.path or "/" query = url_parts.query redirect_url = None with socket.create_connection((host, port)) as sock: if infile: data = infile.read() elif query: data = unquote_to_bytes(query) else: data = b"" encoded_host = host.encode("idna") encoded_path = quote_from_bytes(unquote_to_bytes(path)).encode("ascii") sock.send(b"%s %s %d\r\n" % (encoded_host, encoded_path, len(data))) sock.send(data) fp = sock.makefile("rb") response = fp.readline(4096).decode("ascii").strip("\r\n") print(response, file=sys.stderr, flush=True) parts = response.split(" ", maxsplit=1) code, meta = int(parts[0]), parts[1] if code == 2: shutil.copyfileobj(fp, sys.stdout.buffer) elif code == 3: redirect_url = url_parts._replace(path=meta).geturl() if redirect_url: fetch_url(redirect_url) parser = argparse.ArgumentParser(description="A spartan client") parser.add_argument("url") parser.add_argument("--infile", type=argparse.FileType("rb")) args = parser.parse_args() try: fetch_url(args.url, args.infile) except ValueError as e: print(f"Error: {e}", file=sys.stderr) except KeyboardInterrupt: pass