重构:模块化 RRPP Lite 并更新入口

This commit is contained in:
RoyirinRosmontis
2026-09-16 23:13:28 +08:00
parent c37d8af821
commit 02d36c72f7
35 changed files with 2286 additions and 1079 deletions
+81
View File
@@ -0,0 +1,81 @@
"""PAC 路由引擎使用的纯算法,不依赖文件、网络或 Qt。"""
import ipaddress
import re
def merge_ip_ranges(cidrs, version):
"""将指定 IP 版本的 CIDR 合并为整数闭区间,供二分查找。"""
ranges = []
for cidr in cidrs:
network = ipaddress.ip_network(str(cidr).strip(), strict=False)
if network.version == version:
ranges.append((int(network.network_address), int(network.broadcast_address)))
ranges.sort()
merged = []
for start, end in ranges:
if merged and start <= merged[-1][1] + 1:
if end > merged[-1][1]:
merged[-1] = (merged[-1][0], end)
else:
merged.append((start, end))
return merged
def build_suffix_trie(suffixes):
"""按反向域名标签建立 Trie,适合大规模后缀规则的 O(标签数) 匹配。"""
root = {}
for suffix in suffixes:
node = root
for label in reversed(suffix.split(".")):
node = node.setdefault(label, {})
node[""] = True
return root
def suffix_trie_matches(host: str, trie) -> bool:
"""判断主机名是否命中一个后缀 Trie。"""
node = trie
for label in reversed(host.rstrip(".").lower().split(".")):
node = node.get(label)
if node is None:
return False
if node.get(""):
return True
return bool(node and node.get(""))
def parse_domain_rules(raw_rules, seed_suffixes=()):
"""解析后缀、``full:`` 与 ``regexp:`` 三种 PAC 域名规则。
返回 ``(suffixes, exact, regexes, invalid_regex_count)``。调用方决定
这些规则是“强制代理”还是“明确直连”,从而避免解析层携带业务策略。
"""
suffixes = set(seed_suffixes)
exact = set()
regexes = []
invalid_regexes = 0
for raw in raw_rules or ():
raw_rule = str(raw).strip()
rule = raw_rule.lower()
if not raw_rule:
continue
if rule.startswith("full:"):
host = rule[len("full:"):].rstrip(".")
if host:
exact.add(host)
continue
if rule.startswith("regexp:"):
pattern = raw_rule[len("regexp:"):]
if not pattern:
invalid_regexes += 1
continue
try:
regexes.append(re.compile(pattern, re.IGNORECASE))
except re.error:
invalid_regexes += 1
continue
suffix = rule.lstrip("*.").rstrip(".")
if suffix:
suffixes.add(suffix)
return suffixes, frozenset(exact), tuple(regexes), invalid_regexes