buranun/server.py

163 lines
4.6 KiB
Python
Raw Normal View History

2018-04-08 14:10:21 +00:00
import http.cookies
2018-03-18 19:33:16 +00:00
import http.server
import urllib.parse
2018-04-21 20:09:14 +00:00
import config
import database
2018-03-31 21:12:40 +00:00
import generate_html
2018-06-10 12:33:21 +00:00
import session
2018-03-31 21:12:40 +00:00
2018-03-18 19:33:16 +00:00
class HTTPRequestHandler(http.server.BaseHTTPRequestHandler):
server_version = 'Buranun/0.0'
2018-06-09 14:25:04 +00:00
# TODO: Look into keepalive problems in links2
#protocol_version = 'HTTP/1.1'
protocol_version = 'HTTP/1.0'
2018-03-18 19:33:16 +00:00
2018-06-09 15:59:59 +00:00
def __redirect(self, path = '/', buranun_session = None):
# Construct the URL to redirect to
protocol = 'https' if config.ssl else 'http'
host_port = config.outside_host if config.outside_port == '' else '%s:%s' % (config.outside_host, config.outside_port)
url = '%s://%s%s%s' % (protocol, host_port, config.url_prefix, path)
encoded = url.encode('utf-8')
2018-03-18 19:33:16 +00:00
length = len(encoded)
2018-06-09 15:59:59 +00:00
self.send_response(303)
self.send_header('Location', url)
self.send_header('Content-Type', 'text/plain; charset=utf-8')
self.send_header('Content-Length', length)
2018-06-10 12:33:21 +00:00
# TODO: Make the max-age more sensical
2018-04-08 14:10:21 +00:00
sent_cookies = http.cookies.SimpleCookie()
2018-06-09 15:59:59 +00:00
sent_cookies['buranun_session'] = buranun_session
2018-04-21 20:09:14 +00:00
sent_cookies['buranun_session']['path'] = config.url_prefix if config.url_prefix != '' else '/'
2018-04-08 14:10:21 +00:00
sent_cookies['buranun_session']['max-age'] = 60
2018-04-21 20:09:14 +00:00
sent_cookies['buranun_session']['secure'] = config.ssl
2018-04-08 14:10:21 +00:00
sent_cookies['buranun_session']['httponly'] = True
# Since http.cookies doesn't play nicely with http.server we need to do this manually
self.flush_headers()
self.wfile.write(sent_cookies.output().encode('utf-8') + b'\r\n')
2018-03-18 19:33:16 +00:00
self.end_headers()
self.wfile.write(encoded)
2018-06-09 15:59:59 +00:00
def __send_html(self, html, *, status_code = 200):
encoded = html.encode('utf-8')
length = len(encoded)
self.send_response(status_code)
self.send_header('Content-Type', 'text/html; charset=utf-8')
self.send_header('Content-Length', length)
self.end_headers()
self.wfile.write(encoded)
2018-04-21 20:09:14 +00:00
2018-03-31 21:12:40 +00:00
def __send_404(self, path):
html = generate_html.error_404(path)
self.__send_html(html, status_code = 404)
2018-06-09 15:59:59 +00:00
def do_POST(self):
path = urllib.parse.unquote(self.path)
path_components = [component for component in path.split('/') if component != '']
# Read the POST data
post_data_length = int(self.headers['Content-Length'])
post_data = bytearray()
while len(post_data) < post_data_length:
data = self.rfile.read(post_data_length - len(post_data))
post_data.extend(data)
post_keys = urllib.parse.parse_qs(post_data.decode('utf-8'), keep_blank_values = True)
if len(path_components) == 1 and path_components[0] == 'login':
with database.connect() as db:
username = post_keys['username'][0]
password = post_keys['password'][0]
userid = database.get_userid(db, username)
password_correct = database.check_password(db, userid, password)
if password_correct:
2018-06-10 12:33:21 +00:00
self.__redirect(buranun_session = session.new_session(userid))
else:
# TODO: Have it forward the user back to the page where they were at
html = generate_html.login(self.path, retrying = True)
self.__send_html(html)
2018-06-09 15:59:59 +00:00
else:
self.__send_404(path)
2018-03-18 19:33:16 +00:00
def do_GET(self):
2018-04-08 14:10:21 +00:00
# TODO: Do something with the session
cookies_string = self.headers['cookie']
logged_in = False
2018-04-08 14:10:21 +00:00
if cookies_string is not None:
received_cookies = http.cookies.SimpleCookie()
try:
received_cookies.load(cookies_string)
except http.cookies.CookieError:
print('malformed cookies')
if 'buranun_session' in received_cookies:
2018-06-10 12:43:18 +00:00
sessionid = int(received_cookies['buranun_session'].value)
print(sessionid)
userid = session.get_userid(sessionid)
if userid is not None:
logged_in = True
with database.connect() as db:
print(userid, database.get_user_info(db, userid))
else:
print('unknown session ID')
else:
print('No buranun_session')
2018-04-08 14:10:21 +00:00
else:
print('No cookies')
if not logged_in:
2018-06-09 14:25:04 +00:00
# Display page that tells user to login
# TODO: Have it forward the user back to the page where they were at
html = generate_html.login(self.path)
2018-06-09 14:25:04 +00:00
self.__send_html(html)
# Don't run rest of the function
return
2018-04-08 14:10:21 +00:00
2018-03-18 19:33:16 +00:00
path = urllib.parse.unquote(self.path)
2018-03-31 21:12:40 +00:00
path_components = [component for component in path.split('/') if component != '']
if len(path_components) == 0:
# Path of format / → index
html = generate_html.index()
self.__send_html(html)
elif len(path_components) == 1:
# Path of format /foo/ → board index
board_name = path_components[0]
html = generate_html.board(board_name)
self.__send_html(html)
else:
# Path not understood, send 404
self.__send_404(path)
2018-03-18 19:33:16 +00:00
def main():
2018-04-21 20:09:14 +00:00
# TODO: Don't hardcode
config.load('buranun.conf')
httpd = http.server.HTTPServer(('', config.port), HTTPRequestHandler)
2018-03-18 19:33:16 +00:00
httpd.serve_forever()
if __name__ == '__main__':
main()