fix: sanitize settings JSON, asyncio get_running_loop, Defender exclusion, _btn cleanup, ASCII Save label
Made-with: Cursor
This commit is contained in:
@@ -75,6 +75,63 @@ class Settings:
|
||||
return app_data_dir() / "settings.json"
|
||||
|
||||
|
||||
def sanitize_settings(s: Settings) -> tuple[Settings, bool]:
|
||||
"""Clamp invalid values from hand-edited JSON. Returns (settings, changed)."""
|
||||
changed = False
|
||||
try:
|
||||
cl = int(s.chain_length)
|
||||
if not (1 <= cl <= 8):
|
||||
s.chain_length = max(1, min(8, cl))
|
||||
changed = True
|
||||
except (TypeError, ValueError):
|
||||
s.chain_length = 3
|
||||
changed = True
|
||||
try:
|
||||
p = int(s.local_port)
|
||||
if not (1 <= p <= 65535):
|
||||
s.local_port = max(1, min(65535, p))
|
||||
changed = True
|
||||
except (TypeError, ValueError):
|
||||
s.local_port = 18888
|
||||
changed = True
|
||||
try:
|
||||
if int(s.health_check_seconds) < 10:
|
||||
s.health_check_seconds = 10
|
||||
changed = True
|
||||
except (TypeError, ValueError):
|
||||
s.health_check_seconds = 180
|
||||
changed = True
|
||||
try:
|
||||
if int(s.full_refresh_seconds) < 60:
|
||||
s.full_refresh_seconds = 60
|
||||
changed = True
|
||||
except (TypeError, ValueError):
|
||||
s.full_refresh_seconds = 1800
|
||||
changed = True
|
||||
try:
|
||||
if int(s.validation_concurrency) < 1:
|
||||
s.validation_concurrency = 1
|
||||
changed = True
|
||||
except (TypeError, ValueError):
|
||||
s.validation_concurrency = 64
|
||||
changed = True
|
||||
try:
|
||||
if int(s.max_candidates) < 10:
|
||||
s.max_candidates = 10
|
||||
changed = True
|
||||
except (TypeError, ValueError):
|
||||
s.max_candidates = 400
|
||||
changed = True
|
||||
try:
|
||||
if float(s.validation_timeout_seconds) < 2.0:
|
||||
s.validation_timeout_seconds = 2.0
|
||||
changed = True
|
||||
except (TypeError, ValueError):
|
||||
s.validation_timeout_seconds = 12.0
|
||||
changed = True
|
||||
return s, changed
|
||||
|
||||
|
||||
def normalize_listen_host(s: Settings) -> tuple[Settings, bool]:
|
||||
"""Force loopback bind so LAN/DHCP IP changes (e.g. cloned VMs) never break the listener."""
|
||||
if s.local_host == LISTEN_HOST:
|
||||
@@ -103,7 +160,9 @@ def load_settings() -> Settings:
|
||||
s.pinned_chain = []
|
||||
if not hasattr(s, "manual_exit_proxy") or not isinstance(s.manual_exit_proxy, str):
|
||||
s.manual_exit_proxy = ""
|
||||
s, changed = normalize_listen_host(s)
|
||||
s, ch1 = sanitize_settings(s)
|
||||
s, ch2 = normalize_listen_host(s)
|
||||
changed = ch1 or ch2
|
||||
if changed:
|
||||
try:
|
||||
p.write_text(json.dumps(asdict(s), indent=2), encoding="utf-8")
|
||||
@@ -113,6 +172,7 @@ def load_settings() -> Settings:
|
||||
|
||||
|
||||
def save_settings(s: Settings) -> None:
|
||||
s, _ = sanitize_settings(s)
|
||||
s, _ = normalize_listen_host(s)
|
||||
p = app_data_dir() / "settings.json"
|
||||
p.write_text(json.dumps(asdict(s), indent=2), encoding="utf-8")
|
||||
|
||||
Reference in New Issue
Block a user