63 lines
2.4 KiB
Python
63 lines
2.4 KiB
Python
from server import TLS_ThreadingTCPServer
|
|
import socketserver
|
|
import configparser
|
|
from urllib.parse import urlparse
|
|
import os.path
|
|
import mimetypes
|
|
|
|
mimetypes.init()
|
|
mimetypes.add_type("text/gemini", ".gmi")
|
|
|
|
def is_safe_path(basedir, path, follow_symlinks=True):
|
|
# resolves symbolic links
|
|
if follow_symlinks:
|
|
return os.path.realpath(path).startswith(basedir)
|
|
|
|
return os.path.abspath(path).startswith(basedir)
|
|
|
|
config = configparser.ConfigParser()
|
|
config.read("pygem.ini")
|
|
|
|
class GeminiHandler(socketserver.StreamRequestHandler):
|
|
def handle(self):
|
|
self.url = urlparse(self.rfile.readline().strip())
|
|
if self.url.netloc == b"" and self.url.scheme == b"":
|
|
self.url = urlparse("gemini://%s" % self.rfile.readline().strip())
|
|
# thorough check of the URL
|
|
if self.url.scheme != b"gemini" and self.url.scheme != b"":
|
|
self.wfile.write(("59 URL scheme is not Gemini %s\r\n" % str(self.url)).encode("utf-8"))
|
|
return
|
|
if self.url.netloc.decode("utf-8") != config["gemini"]["domain"] and config["gemini"]["allowProxy"] == "no":
|
|
self.wfile.write("53 \r\n".encode("utf-8"))
|
|
return
|
|
elif self.url.netloc.decode("utf-8") != config["gemini"]["domain"]:
|
|
self.wfile.write("50 Proxying is not implemented yet.\r\n".encode("utf-8"))
|
|
return
|
|
# Actual serving
|
|
file_path = config["server"]["root"] + "/" + self.url.path.decode("utf-8")
|
|
if not is_safe_path(config["server"]["root"], file_path):
|
|
self.wfile.write("50 No.\r\n".encode("utf-8"))
|
|
return
|
|
if os.path.isdir(file_path):
|
|
file_path = file_path + "/index.gmi"
|
|
if not os.path.exists(file_path):
|
|
self.wfile.write("40 File not found.\r\n".encode("utf-8"))
|
|
return
|
|
with open(file_path) as f:
|
|
self.wfile.write(("20 %s\r\n" % mimetypes.guess_type(file_path)[0]).encode("utf-8"))
|
|
self.wfile.write(f.read().encode("utf-8"))
|
|
|
|
server = TLS_ThreadingTCPServer((config['listen']['host'], int(config['listen']['port'])),
|
|
GeminiHandler,
|
|
config['listen']['cert'],
|
|
config['listen']['key'])
|
|
|
|
try:
|
|
print("Starting server...")
|
|
server.serve_forever()
|
|
finally:
|
|
print("Server shutting down...")
|
|
server.shutdown()
|
|
server.server_close()
|
|
|