🏗️ create nix package
This commit is contained in:
parent
54dec72cf8
commit
830f04d710
6 changed files with 143 additions and 86 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
qrcode.png
|
||||||
|
result
|
21
default.nix
Normal file
21
default.nix
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
pkgs ? import <nixpkgs> { },
|
||||||
|
}:
|
||||||
|
|
||||||
|
pkgs.python3Packages.buildPythonApplication rec {
|
||||||
|
pname = "your-package-name";
|
||||||
|
version = "1.0";
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
# Specify the dependencies for the package
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
pkgs.python3Packages.qrcode
|
||||||
|
pkgs.python3Packages.pillow
|
||||||
|
];
|
||||||
|
|
||||||
|
# Entry point of the application
|
||||||
|
# Adjust this path accordingly if share-via-http.py is located in a different directory
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
}
|
12
flake.nix
12
flake.nix
|
@ -31,17 +31,9 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
# Per-system attributes can be defined here. The self' and inputs'
|
packages.default = self'.packages.share-via-http;
|
||||||
# module parameters provide easy access to attributes of the same
|
packages.share-via-http = pkgs.callPackage ./default.nix { };
|
||||||
# system.
|
|
||||||
|
|
||||||
# Equivalent to inputs'.nixpkgs.legacyPackages.hello;
|
|
||||||
packages.default = pkgs.hello;
|
|
||||||
};
|
};
|
||||||
flake = {
|
|
||||||
# The usual flake attributes can be defined here, including system-
|
|
||||||
# agnostic ones like nixosModule and system-enumerating ones, although
|
|
||||||
# those are more easily expressed in perSystem.
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
76
main.py
76
main.py
|
@ -1,76 +0,0 @@
|
||||||
import os
|
|
||||||
import argparse
|
|
||||||
import base64
|
|
||||||
import http.server
|
|
||||||
import socket
|
|
||||||
import socketserver
|
|
||||||
import qrcode
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
# 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.')
|
|
||||||
parser.add_argument('--username', required=True, help='Username for basic authentication.')
|
|
||||||
parser.add_argument('--password', required=True, help='Password for basic authentication.')
|
|
||||||
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):
|
|
||||||
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]
|
|
||||||
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")
|
|
||||||
|
|
||||||
# Set up the server with the AuthHandler and the defined port
|
|
||||||
with socketserver.TCPServer(("", args.port), AuthHandler) 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()
|
|
21
setup.py
Normal file
21
setup.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="share-via-http",
|
||||||
|
version="1.0",
|
||||||
|
packages=find_packages(),
|
||||||
|
install_requires=[
|
||||||
|
"qrcode[pil]",
|
||||||
|
],
|
||||||
|
scripts=["share-via-http.py"],
|
||||||
|
python_requires=">=3.6",
|
||||||
|
author="Your Name",
|
||||||
|
author_email="contact@ingolf-wagner.d",
|
||||||
|
description="Starte a simple HTTP server to share files with basic_auth, generate a QR Code for quick url sharing",
|
||||||
|
url="http://example.org/",
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
],
|
||||||
|
)
|
97
share-via-http.py
Normal file
97
share-via-http.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import base64
|
||||||
|
import http.server
|
||||||
|
import socket
|
||||||
|
import socketserver
|
||||||
|
import qrcode
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
# 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."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--username", required=True, help="Username for basic authentication."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--password", required=True, help="Password for basic authentication."
|
||||||
|
)
|
||||||
|
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):
|
||||||
|
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]
|
||||||
|
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")
|
||||||
|
|
||||||
|
|
||||||
|
# Set up the server with the AuthHandler and the defined port
|
||||||
|
with socketserver.TCPServer(("", args.port), AuthHandler) 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()
|
Loading…
Reference in a new issue