#!/usr/bin/env python3 import requests import subprocess import sys import os import argparse import shlex def launch(command, data): if isinstance(command, str): command = [command] elif isinstance(command, tuple): command = list(command) elif not isinstance(command, list): raise ValueError("`command` must be `list`, `tuple`, or `str`") return subprocess.run(command, input=data) def yn(question, options="yn"): options = options.lower() options_display = f"[{'/'.join(options)}]" full_question = f"{question} {options_display} " response = "WILL NEVER OCCUR IN OPTIONS" while not response in options: response = input(full_question).lower().strip()[0] return response parser = argparse.ArgumentParser( description="Securely run a script from the Internet" ) parser.add_argument("url", help="URL of the script") parser.add_argument( "-i", "--interpreter", help="Choose interpreter to use (default: `bash`)", default="bash", ) group = parser.add_mutually_exclusive_group() group.add_argument( "-p", "--pager", help="Choose pager to use (default: `less`)", default="less", ) group.add_argument( "-s", "--skip-pager", action="store_true", help="Skip pager and confirmation; run script immediately", ) group.add_argument( "-q", "--quiet", action="store_true", help="Skip pager and confirmation; run script immediately; do not print anything", ) args = parser.parse_args() url = args.url pager = shlex.split(args.pager) interpreter = shlex.split(args.interpreter) while True: if not args.quiet: print(f"Downloading `{url}`...") response = requests.get(url, allow_redirects=False) if response.status_code == 200: content = response.content break else: try: print(f"{response.status_code} {response.reason} (redirect to `{response.headers['location']}`)") if yn("Do you want to follow this redirect?") == 'y': url = response.headers['location'] else: print("Not redirecting.") sys.exit(0) except KeyError: print(f"Download failed: {response.status_code} {response.reason}") sys.exit(0) if not args.quiet: print("Download successful.") print("=" * os.get_terminal_size().columns) if args.skip_pager or args.quiet: launch(interpreter, content) else: launch(pager, content) response = yn("Do you want to run this script?") if response == "y": print("=" * os.get_terminal_size().columns) launch(interpreter, content) else: print("=" * os.get_terminal_size().columns) print("Script not run.")