#!/usr/bin/env python import os import argparse import base64 import http.server import socket import socketserver import qrcode import random import string from functools import partial def get_current_ip_address(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ip_address = s.getsockname()[0] s.close() return ip_address def generate_default_username(): return "".join(random.choices(string.ascii_lowercase + string.digits, k=8)) def generate_default_password(): return "".join(random.choices(string.ascii_letters + string.digits, k=12)) # Define the command-line arguments parser = argparse.ArgumentParser( description="Start a simple HTTP server with basic authentication." ) parser.add_argument( "--port", type=int, default=8000, help="Port to serve the directory over. Defaults to 8000.", ) parser.add_argument( "--username", default=generate_default_username(), help="Username for basic authentication. Generates one if not set", ) parser.add_argument( "--password", default=generate_default_password(), help="Password for basic authentication. Generates one if not set", ) parser.add_argument( "--directory", default=os.getcwd(), help="Directory to serve. Defaults to the current directory.", ) arguments = parser.parse_args() # Change the working directory to serve the specified directory os.chdir(os.path.expanduser(arguments.directory)) # Define a request handler with basic authentication class AuthHandler(http.server.SimpleHTTPRequestHandler): def __init__(self, username, passsword, *args, **kwargs): self.base64_encoded_string = base64.b64encode( f"{username}:{passsword}".encode("utf-8") ).decode("utf-8") super().__init__(*args, **kwargs) def do_AUTHHEAD(self): self.send_response(401) self.send_header("WWW-Authenticate", 'Basic realm="Server Access"') self.send_header("Content-type", "text/html") self.end_headers() def do_GET(self): auth_header = self.headers.get("Authorization") if auth_header is None or not self.check_auth(auth_header): self.do_AUTHHEAD() self.wfile.write(b"Not authenticated") else: super().do_GET() def check_auth(self, auth_header): encoded_credentials = auth_header.split()[1] return encoded_credentials == self.base64_encoded_string def save_qr_code(url): qr_code = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4, ) qr_code.add_data(url) qr_code.make(fit=True) image = qr_code.make_image(fill_color="black", back_color="white").convert("RGB") image.save("qrcode.png") # Set up the server with the AuthHandler and the defined port auth_handler = partial(AuthHandler, arguments.username, arguments.password) with socketserver.TCPServer(("", arguments.port), auth_handler) as httpd: print("qrcode.png is saved in the current directory.") ip_address = get_current_ip_address() server_url = f"http://{arguments.username}:{arguments.password}@{ip_address}:{arguments.port}" print(f"{server_url} < server url") print(f"{server_url}/qrcode.png < qrcode") print("press Ctr-C to stop server") save_qr_code(server_url) httpd.serve_forever()