2021-11-25 11:29:02 +01:00
|
|
|
"""Smol CGI utilities."""
|
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
from os import environ
|
2021-11-25 11:29:02 +01:00
|
|
|
from pathlib import Path
|
2021-11-24 22:12:36 +01:00
|
|
|
from urllib.parse import unquote
|
2021-08-31 17:52:02 +02:00
|
|
|
|
2021-11-25 11:29:02 +01:00
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
def getenv(name):
|
|
|
|
return environ.get(name, "")
|
|
|
|
|
2021-11-25 11:29:02 +01:00
|
|
|
|
2021-11-24 22:12:36 +01:00
|
|
|
gateway_interface = getenv("GATEWAY_INTERFACE")
|
|
|
|
remote_addr = getenv("REMOTE_ADDR")
|
|
|
|
remote_host = getenv("REMOTE_HOST")
|
|
|
|
request_method = getenv("REQUEST_METHOD")
|
|
|
|
script_name = getenv("SCRIPT_NAME")
|
|
|
|
server_name = getenv("SERVER_NAME")
|
|
|
|
server_port = getenv("SERVER_PORT")
|
|
|
|
server_protocol = getenv("SERVER_PROTOCOL")
|
|
|
|
server_software = getenv("SERVER_SOFTWARE")
|
|
|
|
gemini_document_root = getenv("GEMINI_DOCUMENT_ROOT")
|
|
|
|
gemini_script_filename = getenv("GEMINI_SCRIPT_FILENAME")
|
|
|
|
gemini_url = getenv("GEMINI_URL")
|
|
|
|
gemini_url_path = getenv("GEMINI_URL_PATH")
|
2021-08-31 17:52:02 +02:00
|
|
|
tls_version = getenv("TLS_VERSION")
|
2021-11-24 22:12:36 +01:00
|
|
|
tls_cipher = getenv("TLS_CIPHER")
|
|
|
|
path_info = getenv("PATH_INFO")
|
|
|
|
query_string = getenv("QUERY_STRING")
|
2021-08-31 17:52:02 +02:00
|
|
|
auth_type = getenv("AUTH_TYPE")
|
2021-11-24 22:12:36 +01:00
|
|
|
remote_user = getenv("REMOTE_USER")
|
|
|
|
tls_client_issuer = getenv("TLS_CLIENT_ISSUER")
|
|
|
|
tls_client_hash = getenv("TLS_CLIENT_HASH")
|
|
|
|
tls_client_not_after = getenv("TLS_CLIENT_NOT_AFTER")
|
|
|
|
tls_client_not_before = getenv("TLS_CLIENT_NOT_BEFORE")
|
|
|
|
|
|
|
|
query_string_dec = unquote(query_string)
|
2021-08-31 17:52:02 +02:00
|
|
|
|
|
|
|
cgi_vars = [
|
2021-11-24 22:12:36 +01:00
|
|
|
"gateway_interface", "remote_addr", "remote_host", "request_method",
|
|
|
|
"script_name", "server_name", "server_port", "server_protocol",
|
|
|
|
"server_software", "gemini_document_root", "gemini_script_filename",
|
|
|
|
"gemini_url", "gemini_url_path", "tls_version", "tls_cipher", "path_info",
|
|
|
|
"query_string", "auth_type", "remote_user", "tls_client_issuer",
|
|
|
|
"tls_client_hash", "tls_client_not_after", "tls_client_not_before",
|
|
|
|
"query_string_dec",
|
2021-08-31 17:52:02 +02:00
|
|
|
]
|
|
|
|
|
2021-11-25 11:29:02 +01:00
|
|
|
|
|
|
|
def get_storage_path():
|
|
|
|
script_filename = script_name.split("/")[-1]
|
|
|
|
path = getenv(f"GEMINI_{script_filename.upper()}_STORAGE")
|
|
|
|
if not path:
|
|
|
|
path = f"/home/gemini/storage/{script_filename}"
|
|
|
|
path = Path(path)
|
|
|
|
if not path.exists():
|
|
|
|
path.mkdir(parents=True)
|
|
|
|
return path
|
|
|
|
|
|
|
|
|
|
|
|
def get_user_dir():
|
|
|
|
user_dir = get_storage_path() / tls_client_hash[7:]
|
|
|
|
if not user_dir.is_dir():
|
|
|
|
user_dir.mkdir()
|
|
|
|
return user_dir
|
|
|
|
|
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
def header(code, meta):
|
|
|
|
print(f"{code} {meta}", end="\r\n")
|
|
|
|
|
2021-11-25 11:29:02 +01:00
|
|
|
|
2021-11-27 12:49:30 +01:00
|
|
|
def success(mime):
|
|
|
|
header(20, mime)
|
|
|
|
|
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
def exit_with_header(code, meta):
|
|
|
|
header(code, meta)
|
|
|
|
exit()
|
|
|
|
|
2021-11-25 11:29:02 +01:00
|
|
|
|
2021-11-27 12:49:30 +01:00
|
|
|
def require_input(reason=""):
|
2021-11-25 11:29:02 +01:00
|
|
|
exit_with_header(10, reason)
|
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
|
2021-11-27 12:49:30 +01:00
|
|
|
def require_sensitive_input(reason=""):
|
|
|
|
exit_with_header(11, reason)
|
|
|
|
|
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
def redirect_temp(url):
|
|
|
|
exit_with_header(30, url)
|
|
|
|
|
2021-11-25 11:29:02 +01:00
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
def redirect_perm(url):
|
|
|
|
exit_with_header(31, url)
|
|
|
|
|
|
|
|
|
2021-11-27 12:49:30 +01:00
|
|
|
def temp_error(reason=""):
|
|
|
|
exit_with_header(40, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def server_unavailable(reason=""):
|
|
|
|
exit_with_header(41, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def cgi_error(reason=""):
|
2021-11-25 11:29:02 +01:00
|
|
|
exit_with_header(42, reason)
|
|
|
|
|
|
|
|
|
2021-11-27 12:49:30 +01:00
|
|
|
def proxy_error(reason=""):
|
|
|
|
exit_with_header(43, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def slow_down(num_seconds):
|
|
|
|
exit_with_header(44, num_seconds)
|
|
|
|
|
|
|
|
|
|
|
|
def perm_error(reason=""):
|
|
|
|
exit_with_header(50, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def not_found(reason=""):
|
2021-11-25 11:29:02 +01:00
|
|
|
exit_with_header(51, reason)
|
|
|
|
|
|
|
|
|
2021-11-27 12:49:30 +01:00
|
|
|
def gone(reason=""):
|
|
|
|
exit_with_header(52, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def proxy_request_refused(reason=""):
|
|
|
|
exit_with_header(53, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def bad_request(reason=""):
|
2021-11-25 11:29:02 +01:00
|
|
|
exit_with_header(59, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def require_client_cert():
|
|
|
|
if auth_type != "CERTIFICATE":
|
|
|
|
exit_with_header(60, "You need a certificate to use this app")
|
2021-08-31 17:52:02 +02:00
|
|
|
|
|
|
|
|
2021-11-27 12:49:30 +01:00
|
|
|
def cert_not_authorised(reason=""):
|
|
|
|
exit_with_header(61, reason)
|
|
|
|
|
|
|
|
|
|
|
|
def cert_not_valid(reason=""):
|
|
|
|
exit_with_header(62, reason)
|
|
|
|
|
|
|
|
|
2021-08-31 17:52:02 +02:00
|
|
|
def print_env():
|
|
|
|
globz = globals()
|
|
|
|
for key in cgi_vars:
|
|
|
|
print(f"{key} = {repr(globz[key])}")
|
2021-11-25 11:29:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
def link(path, text=""):
|
|
|
|
print(f"=> {script_name}{path} {text}")
|