2024-11-16 23:02:15 +01:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
import os
|
|
|
|
import argparse
|
|
|
|
import base64
|
|
|
|
import http.server
|
|
|
|
import socket
|
|
|
|
import socketserver
|
|
|
|
import qrcode
|
2024-11-17 01:06:32 +01:00
|
|
|
import random
|
|
|
|
import string
|
2024-11-17 01:32:06 +01:00
|
|
|
from functools import partial
|
2024-11-16 23:02:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2024-11-17 01:06:32 +01:00
|
|
|
def generate_default_username():
|
2024-11-17 01:24:29 +01:00
|
|
|
return "".join(random.choices(string.ascii_lowercase + string.digits, k=8))
|
2024-11-17 01:06:32 +01:00
|
|
|
|
|
|
|
|
|
|
|
def generate_default_password():
|
2024-11-17 01:24:29 +01:00
|
|
|
return "".join(random.choices(string.ascii_letters + string.digits, k=12))
|
2024-11-17 01:06:32 +01:00
|
|
|
|
|
|
|
|
2024-11-16 23:02:15 +01:00
|
|
|
# Define the command-line arguments
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description="Start a simple HTTP server with basic authentication."
|
|
|
|
)
|
2024-11-17 01:06:32 +01:00
|
|
|
|
2024-11-16 23:02:15 +01:00
|
|
|
parser.add_argument(
|
2024-11-17 01:06:32 +01:00
|
|
|
"--port",
|
|
|
|
type=int,
|
|
|
|
default=8000,
|
|
|
|
help="Port to serve the directory over. Defaults to 8000.",
|
2024-11-16 23:02:15 +01:00
|
|
|
)
|
2024-11-17 01:06:32 +01:00
|
|
|
|
2024-11-16 23:02:15 +01:00
|
|
|
parser.add_argument(
|
2024-11-17 01:06:32 +01:00
|
|
|
"--username",
|
|
|
|
default=generate_default_username(),
|
|
|
|
help="Username for basic authentication. Generates one if not set",
|
2024-11-16 23:02:15 +01:00
|
|
|
)
|
2024-11-17 01:06:32 +01:00
|
|
|
|
2024-11-16 23:02:15 +01:00
|
|
|
parser.add_argument(
|
2024-11-17 01:06:32 +01:00
|
|
|
"--password",
|
|
|
|
default=generate_default_password(),
|
|
|
|
help="Password for basic authentication. Generates one if not set",
|
2024-11-16 23:02:15 +01:00
|
|
|
)
|
2024-11-17 01:06:32 +01:00
|
|
|
|
2024-11-16 23:02:15 +01:00
|
|
|
parser.add_argument(
|
|
|
|
"--directory",
|
|
|
|
default=os.getcwd(),
|
|
|
|
help="Directory to serve. Defaults to the current directory.",
|
|
|
|
)
|
2024-11-17 01:06:32 +01:00
|
|
|
|
2024-11-17 01:32:06 +01:00
|
|
|
arguments = parser.parse_args()
|
2024-11-16 23:02:15 +01:00
|
|
|
|
|
|
|
# Change the working directory to serve the specified directory
|
2024-11-17 01:32:06 +01:00
|
|
|
os.chdir(os.path.expanduser(arguments.directory))
|
2024-11-16 23:02:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
# Define a request handler with basic authentication
|
|
|
|
class AuthHandler(http.server.SimpleHTTPRequestHandler):
|
2024-11-17 01:24:29 +01:00
|
|
|
def __init__(self, username, passsword, *args, **kwargs):
|
2024-11-17 01:32:06 +01:00
|
|
|
self.base64_encoded_string = base64.b64encode(
|
|
|
|
f"{username}:{passsword}".encode("utf-8")
|
|
|
|
).decode("utf-8")
|
2024-11-17 01:24:29 +01:00
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
2024-11-16 23:02:15 +01:00
|
|
|
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]
|
2024-11-17 01:32:06 +01:00
|
|
|
return encoded_credentials == self.base64_encoded_string
|
2024-11-16 23:02:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
def save_qr_code(url):
|
2024-11-17 01:32:06 +01:00
|
|
|
qr_code = qrcode.QRCode(
|
2024-11-16 23:02:15 +01:00
|
|
|
version=1,
|
|
|
|
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
|
|
|
box_size=10,
|
|
|
|
border=4,
|
|
|
|
)
|
2024-11-17 01:32:06 +01:00
|
|
|
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")
|
2024-11-16 23:02:15 +01:00
|
|
|
|
2024-11-17 01:24:29 +01:00
|
|
|
|
2024-11-16 23:02:15 +01:00
|
|
|
# Set up the server with the AuthHandler and the defined port
|
2024-11-17 01:32:06 +01:00
|
|
|
auth_handler = partial(AuthHandler, arguments.username, arguments.password)
|
|
|
|
with socketserver.TCPServer(("", arguments.port), auth_handler) as httpd:
|
2024-11-16 23:02:15 +01:00
|
|
|
print("qrcode.png is saved in the current directory.")
|
|
|
|
ip_address = get_current_ip_address()
|
2024-11-17 01:32:06 +01:00
|
|
|
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)
|
2024-11-16 23:02:15 +01:00
|
|
|
httpd.serve_forever()
|