Files
adlist_mikrotik/adlist/validation.py
T
2026-10-09 10:53:10 +02:00

91 lines
2.6 KiB
Python

"""Pure input validation and supported host-list line formats."""
import ipaddress
import re
from urllib.parse import urlparse
def should_ignore_domain(domain):
return domain.startswith(".") or any(
ch in domain for ch in ["~", "=", "$", "'", "^", "_", ">", "<", ":"]
)
def should_ignore_line(line):
return any(sym in line for sym in ["<", ">", "##", "###", "div", "span"])
def is_valid_domain(domain):
return bool(re.compile(r"^(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$").match(domain))
def convert_host_line(line: str, target_ip: str):
# szybkie odrzucenia
if not line:
return None
line = line.strip()
if not line or line.startswith(("!", "#", "/", ";")):
return None
for sep in (" #", " ;"):
idx = line.find(sep)
if idx != -1:
line = line[:idx].rstrip()
if not line:
return None
m = re.match(r"^\|\|([a-z0-9.-]+)\^", line, re.IGNORECASE)
if m:
domain = m.group(1).strip(".")
if not should_ignore_domain(domain) and is_valid_domain(domain):
return f"{target_ip} {domain}"
return None
parts = line.split()
if len(parts) >= 2 and (
re.match(r"^\d{1,3}(?:\.\d{1,3}){3}$", parts[0]) or ":" in parts[0]
):
domain = parts[1].strip().split("#", 1)[0].strip().strip(".")
if not should_ignore_domain(domain) and is_valid_domain(domain):
return f"{target_ip} {domain}"
return None
m = re.match(r"^(?:address|server)=/([a-z0-9.-]+)/", line, re.IGNORECASE)
if m:
domain = m.group(1).strip(".")
if not should_ignore_domain(domain) and is_valid_domain(domain):
return f"{target_ip} {domain}"
return None
token = parts[0].split("#", 1)[0].strip().strip(".")
if token and not should_ignore_domain(token) and is_valid_domain(token):
return f"{target_ip} {token}"
return None
def validate_and_normalize_url(url):
url = (url or "").strip()
# prosta sanity-check: usuń CR/LF
if any(c in url for c in ("\r", "\n")):
raise ValueError("Invalid characters in URL")
parsed = urlparse(url)
if not parsed.scheme:
url = f"https://{url}"
parsed = urlparse(url)
# akceptuj tylko http/https
if parsed.scheme not in {"http", "https"}:
raise ValueError(f"Unsupported scheme: {parsed.scheme}")
if not parsed.netloc:
raise ValueError("Missing host in URL")
return parsed.geturl()
def validate_ip(value: str) -> str:
v = (value or "").strip()
try:
return str(ipaddress.ip_address(v))
except Exception:
raise ValueError("Invalid IP address")