share-host/share-via-http.py

132 lines
3.9 KiB
Python
Raw Normal View History

#!/usr/bin/env python
import os
import argparse
import base64
import http.server
import socket
import socketserver
import qrcode
import random
import string
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
# Function to generate a default username
def generate_default_username():
2024-11-17 01:24:29 +01:00
return "".join(random.choices(string.ascii_lowercase + string.digits, k=8))
# Function to generate a default password
def generate_default_password():
2024-11-17 01:24:29 +01:00
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.",
)
args = parser.parse_args()
# Expand the directory path (e.g., if it contains ~)
expanded_directory = os.path.expanduser(args.directory)
# Change the working directory to serve the specified directory
os.chdir(expanded_directory)
# 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):
encoded_bytes = base64.b64encode(f"{username}:{passsword}".encode("utf-8"))
# Convert bytes back to string
self.encoded_str = encoded_bytes.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]
2024-11-17 01:24:29 +01:00
return encoded_credentials == self.encoded_str
# decoded_credentials = base64.b64decode(encoded_credentials).decode("utf-8")
# username, password = decoded_credentials.split(":")
# return username == args.username and password == args.password
def save_qr_code(url):
# Generate the QR code
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(url)
qr.make(fit=True)
# Create an image from the QR Code instance
img = qr.make_image(fill_color="black", back_color="white").convert("RGB")
# Save the image
img.save("qrcode.png")
2024-11-17 01:24:29 +01:00
from functools import partial
# Set up the server with the AuthHandler and the defined port
2024-11-17 01:24:29 +01:00
auth_handler = partial(AuthHandler, args.username, args.password)
with socketserver.TCPServer(("", args.port), auth_handler) as httpd:
print("qrcode.png is saved in the current directory.")
ip_address = get_current_ip_address()
print(
f"http://{args.username}:{args.password}@{ip_address}:{args.port}/ < the page"
)
print(
f"http://{args.username}:{args.password}@{ip_address}:{args.port}/qrcode.png < qrcode"
)
save_qr_code(f"http://{args.username}:{args.password}@{ip_address}:{args.port}/")
httpd.serve_forever()