From 4eada650401c57f45aca9d9145590f4dbf02f470 Mon Sep 17 00:00:00 2001 From: Nova Date: Wed, 20 Aug 2025 15:39:14 +0200 Subject: [PATCH] First testing version of what will become 2.0 Partial new config functionality. --- new_conf.conf | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ pywebsrv.py | 52 +++++++++++++++++++++++++-------------------- 2 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 new_conf.conf diff --git a/new_conf.conf b/new_conf.conf new file mode 100644 index 0000000..7a2bfc3 --- /dev/null +++ b/new_conf.conf @@ -0,0 +1,58 @@ +# NOTE: +# New functions: +# match(String,Boolean): +# String: The string to match. +# Boolean: Case sensitivity. +# General info: +# The match command is used for UA-based blocking. Will block +# anything that matches the String. + +# NOTE: +# Custom (sorta) datatypes. +# String: +# NSCL 2.0 equivalent of Pythons `str`. +# Integer: +# NSCL 2.0 equivalent of Pythons `int`. +# Boolean: +# NSCL 2.0 implementation of a Boolean. Supported inputs: +# 0: False +# 1: True + +# NOTE: +# This is a beta of NSCL 2.0 +# Current version: NSCL 2.0-raw-alpha0 +# The NSCL 1.3 spec and sample parser is uploaded to: +# https://git.novacow.ch/Nova/nscl-1.3-spec/ +# The 2.0 spec will be uploaded to: +# https://git.novacow.ch/Nova/nscl-2.0-spec/ + +# WARNING: This is an alpha spec of NSCL 2.0!! + +host example.com { + directory:/home/nova/Downloads/test/html + allowed-methods:GET + block-ip:match-ip("192.168",2) + block-ua:match("Discordbot",0),match("Google",0) +} + +host cdn.example.com { + directory:/home/nova/Downloads/test/cdn + allowed-methods:GET,PUT + block-ip:10.1.100.2 + block-ua:match("Discordbot",0) +} + +host modem.example.com { + proxy:192.168.2.254 + key-file:/home/nova/Downloads/test/proxykey.pem + cert-file:/home/nova/Downloads/test/proxycert.pem +} + +globals { + http:1 + https:1 + port:8080 + https-port:8443 + global-key:/home/nova/Downloads/test/key.pem + global-cert:/home/nova/Downloads/test/cert.pem +} diff --git a/pywebsrv.py b/pywebsrv.py index 65da83c..a68ebb8 100644 --- a/pywebsrv.py +++ b/pywebsrv.py @@ -59,9 +59,11 @@ except ImportError: class FileHandler: CONFIG_FILE = "pywebsrv.conf" + new_conf = "new_conf.conf" def __init__(self, base_dir=None): self.config_path = os.path.join(os.getcwd(), self.CONFIG_FILE) + self.new_conf = os.path.join(os.getcwd(), self.new_conf) self.base_dir = self.read_config("directory") self.cached_conf = None if not os.path.exists(self.config_path): @@ -166,7 +168,7 @@ class FileHandler: Reads the configuration file and returns a dict """ if self.cached_conf is None: - with open(self.config_path, "r", encoding="utf-8") as fh: + with open(self.new_conf, "r", encoding="utf-8") as fh: text = fh.read() blocks = re.findall( @@ -174,6 +176,7 @@ class FileHandler: ) parsed = {} host_list = [] + print(f"Blocks: {blocks}") for tag, hostname, body in blocks: section = hostname if hostname else "globals" if hostname: @@ -181,7 +184,7 @@ class FileHandler: kv = {} for line in body.splitlines(): line = line.strip() - if not line or ":" not in line or line.starswith("#"): + if not line or ":" not in line or line.startswith("#"): continue key, rest = line.split(":", 1) @@ -193,18 +196,18 @@ class FileHandler: kv[key] = [item.strip() for item in rest.split(",")] else: kv[key] = rest - parsed[section] = kv - parsed["globals"]["hosts"] = host_list - self.cached_conf = parsed - else: - parsed = self.cached_conf - if option == "host": - try: - return host_list - except Exception: - return parsed["globals"]["hosts"] - section = parsed.get(host or "globals", {}) - return section.get(option) + parsed[section] = kv + parsed["globals"]["hosts"] = host_list + self.cached_conf = parsed + else: + parsed = self.cached_conf + if option == "host": + try: + return host_list + except Exception: + return parsed["globals"]["hosts"] + section = parsed.get(host or "globals", {}) + return section.get(option) def autocert(self): """ @@ -218,7 +221,8 @@ class FileHandler: class RequestParser: def __init__(self): self.file_handler = FileHandler() - self.hosts = self.file_handler.read_config("host") + self.hosts = self.file_handler.read_new_config("host") + print(f"Hosts: {self.hosts}") def parse_request_line(self, line): """Parses the HTTP request line.""" @@ -230,8 +234,9 @@ class RequestParser: path += "index.html" return method, path, version - def ua_blocker(self, ua): + def ua_blocker(self, ua, host=None): """Parses and matches UA to block""" + del host match, literal = self.file_handler.read_config("block-ua") if ua in literal: return False @@ -284,8 +289,8 @@ class WebServer: def __init__( self, http_port=8080, https_port=8443, cert_file="cert.pem", key_file="key.pem" ): - self.http_port = http_port - self.https_port = https_port + self.http_port = int(http_port) + self.https_port = int(https_port) self.cert_file = cert_file self.key_file = key_file self.file_handler = FileHandler() @@ -583,12 +588,13 @@ class WebServer: def main(): file_handler = FileHandler() - file_handler.check_first_run() file_handler.base_dir = file_handler.read_config("directory") - http_port = file_handler.read_config("port") or 8080 - https_port = file_handler.read_config("port-https") or 8443 - http_enabled = file_handler.read_config("http") or True - https_enabled = file_handler.read_config("https") or False + http_port = file_handler.read_new_config("port") or 8080 + https_port = file_handler.read_new_config("port-https") or 8443 + http_enabled = bool(file_handler.read_new_config("http")) or True + print(http_enabled) + https_enabled = bool(file_handler.read_new_config("https")) or False + print(https_enabled) server = WebServer(http_port=http_port, https_port=https_port) server.start(http_enabled, https_enabled)