import json import config import cgi import os import sqlite3 import mimetypes def playout(filename, content = "text/html"): return ["", [('Content-Type', content if content else "application/binary"), ("X-Accel-Redirect", filename)], None] def home(): return ["", [('Content-Type','text/html'), ("Location", config.homepage)], "302 Home"] def target_filename_internal(session, filename): target = session["path"] + "/" if filename: target += filename if config.user_subdirs: target = session["user"] + "/" + target return target def target_filename(session, file): return config.fileroot + target_filename_internal(session, file) def resolve_alias(alias): session = None db = sqlite3.connect(config.database, check_same_thread = False) cursor = db.cursor() cursor.execute("SELECT user, real, access, storage, display FROM aliases WHERE alias=:alias", {"alias": alias}) data = cursor.fetchone() if data: session = {"user": data[0], "path": data[1], "access": data[2], "limit": data[3], "display": data[4]} else: print("Unknown alias " + alias) db.close() return session def listing(session): listing = {"total": 0, "files": [], "access": session["access"], "display": session["display"]} if 'r' in session["access"]: directory = target_filename(session, None) files = os.listdir(directory) for filename in files: if os.path.isfile(directory + filename): size = os.path.getsize(directory + filename) listing["files"].append({"name": filename, "size": size}) listing["total"] += size return [json.dumps(listing), [('Content-Type','application/json')], "200 OK"] def upload(session, post): if 'c' not in session["access"]: return ["", [('Content-Type','text/html')], "403 No"] if post["file"].filename: target = target_filename(session, os.path.basename(post["file"].filename)) while os.path.isfile(target): target += "_dup" try: open(target, 'wb').write(post["file"].file.read()) print("Uploaded " + target) return ["", [('Content-Type','text/html')], "200 OK"] except PermissionError as e: print("Failed to store " + target + ": " + e.msg) return ["", [('Content-Type','text/html')], "500 Error"] else: print("Upload failed") return ["", [('Content-Type','text/html')], "500 Error"] def route(path, env, session, post): # Get mapped user/path/limits session = resolve_alias(path[0]) if not session: return home() print(json.dumps(session)) if len(path) > 1 and path[1] == "upload": return upload(session, post) if len(path) > 1 and path[1] == "listing": return listing(session) if len(path) > 1 and path[1] == "file": print("/data/" + target_filename_internal(session, path[2])) return playout("/data/" + target_filename_internal(session, path[2]), mimetypes.guess_type(path[2])[0]) if len(path) > 1 and path[1] == "preview" and session["display"] == "gallery": return playout("/data/" + target_filename_internal(session, "preview/" + path[2]), mimetypes.guess_type(path[2])[0]) return playout("/interface/listing.htm") def handle_request(env, response): path = env.get('PATH_INFO', '').lstrip('/').split('/') post = None headers = [] session = None # Read POST data try: if env.get('CONTENT_TYPE', '').startswith("multipart/form-data"): post = cgi.FieldStorage(environ=env, fp=env['wsgi.input'], keep_blank_values=True) else: content_length = int(env.get('CONTENT_LENGTH', '0')) post_raw = env["wsgi.input"].read(content_length).decode('utf-8') post = post_raw except ValueError as e: post = None # Route request data, addtl_headers, code = route(path, env, session, post) headers.extend(addtl_headers) response(code if code else "200 OK", headers) return [bytes(data, "utf-8")]