aboutsummaryrefslogtreecommitdiff
path: root/backend/main.py
blob: 592b7a38498e3b22839e01857e226187207fa6ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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 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]}
	else:
		print("Unknown alias " + alias)
	db.close()
	return session

def listing(session):
	listing = {"total": 0, "files": []}
	if 'r' not in session["access"]:
		return ["", [('Content-Type','text/html')], "403 No"]

	directory = target_filename(session, None)
	files = os.listdir(directory)

	for filename in files:
		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))
		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])

	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")]