|
#!/usr/bin/env python3 |
|
import os |
|
import http.server |
|
import socketserver |
|
import random |
|
import string |
|
from urllib.parse import unquote |
|
from cgi import FieldStorage |
|
|
|
PORT = 8000 |
|
FILES_DIR = "files" |
|
ACCESS_CODE = ''.join(random.choices(string.digits, k=6)) |
|
os.makedirs(FILES_DIR, exist_ok=True) |
|
|
|
HTML_PAGE = """ |
|
<!DOCTYPE html> |
|
<html> |
|
<head><title>File Share</title></head> |
|
<body> |
|
<script> |
|
const CODE = "{}"; |
|
const cookie = document.cookie.split('; ').find(r => r.startsWith('access_code=')); |
|
let accessOK = cookie && cookie.split('=')[1] === CODE; |
|
|
|
if (!accessOK) {{ |
|
const input = prompt("Enter access code:"); |
|
if (input !== CODE) {{ |
|
document.body.innerHTML = "<h1>Access denied</h1>"; |
|
throw new Error("Forbidden"); |
|
}} else {{ |
|
document.cookie = "access_code=" + input + "; path=/"; |
|
location.reload(); |
|
}} |
|
}} else {{ |
|
document.write(` |
|
<h2>Upload File</h2> |
|
<form enctype="multipart/form-data" method="post"> |
|
<input name="file" type="file"/> |
|
<input type="submit" value="Upload"/> |
|
</form> |
|
<h2>Files</h2> |
|
<ul> |
|
{} |
|
</ul> |
|
`); |
|
}} |
|
</script> |
|
</body> |
|
</html> |
|
""" |
|
|
|
class Handler(http.server.SimpleHTTPRequestHandler): |
|
def has_valid_code(self): |
|
cookie_header = self.headers.get('Cookie', '') |
|
for cookie in cookie_header.split(';'): |
|
if cookie.strip().startswith('access_code='): |
|
value = cookie.strip().split('=')[1] |
|
return value == ACCESS_CODE |
|
return False |
|
|
|
def list_files(self): |
|
files = os.listdir(FILES_DIR) |
|
return [f"<li><a href='/files/{f}'>{f}</a></li>" for f in files if os.path.isfile(os.path.join(FILES_DIR, f))] |
|
|
|
def do_GET(self): |
|
if self.path == '/': |
|
# Always serve this, even without cookie |
|
file_links = "\n".join(self.list_files()) |
|
content = HTML_PAGE.format(ACCESS_CODE, file_links).encode() |
|
self.send_response(200) |
|
self.send_header("Content-type", "text/html") |
|
self.send_header("Content-Length", str(len(content))) |
|
self.end_headers() |
|
self.wfile.write(content) |
|
elif self.path.startswith('/files/'): |
|
if not self.has_valid_code(): |
|
self.send_error(403, "Access code required") |
|
return |
|
file_path = os.path.join(FILES_DIR, os.path.basename(unquote(self.path[len('/files/'):]))) |
|
|
|
if os.path.exists(file_path): |
|
self.path = '/' + file_path |
|
return http.server.SimpleHTTPRequestHandler.do_GET(self) |
|
else: |
|
self.send_error(404, "File not found") |
|
else: |
|
self.send_error(403) |
|
|
|
def do_POST(self): |
|
if not self.has_valid_code(): |
|
self.send_error(403, "Access code required") |
|
return |
|
|
|
form = FieldStorage(fp=self.rfile, headers=self.headers, environ={ |
|
'REQUEST_METHOD': 'POST', |
|
'CONTENT_TYPE': self.headers['Content-Type'], |
|
}) |
|
file_field = form['file'] |
|
if file_field.filename: |
|
dest_path = os.path.join(FILES_DIR, os.path.basename(file_field.filename)) |
|
with open(dest_path, 'wb') as f: |
|
f.write(file_field.file.read()) |
|
self.send_response(303) |
|
self.send_header('Location', '/') |
|
self.end_headers() |
|
|
|
if __name__ == "__main__": |
|
print(f"Access code: {ACCESS_CODE}") |
|
print(f"Serving at http://0.0.0.0:{PORT}") |
|
with socketserver.TCPServer(("", PORT), Handler) as httpd: |
|
httpd.serve_forever() |