feat: install, update and remove Mudfish from the panel

- Install: download the latest package from mudfish.net, verify the
  Makeself MD5, unpack the bzip2 tar ourselves (no installer script is
  executed; path traversal and links rejected) into /opt/mudfish/<ver>.
- Update: checked at most daily; button-only; refused while the tunnel is
  up; carries the saved login (.conf, .conf.db) into the new version,
  restarts the daemon and keeps only the previous version.
- Remove: button with confirmation, and automatically when the plugin is
  uninstalled: VPN off, daemon stopped, mudfish-tap removed,
  /opt/mudfish deleted, plugin settings cleared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ysj7705andClaude Opus 5.5 committed 2026-10-24 21:58:32 +09:00
1 parent 027a029b47
commit 3c28c9dac2
9 files changed
+718 -27

No files matched your search

+14
View File
@@ -37,6 +37,20 @@ def find_mudfish(root: str = MUDFISH_ROOT) -> Optional[Tuple[str, str]]:
return os.path.join(root, name, "bin", "mudrun-headless"), os.path.join(root, name, "var")
def version_of(bin_path: str) -> str:
"""'/opt/mudfish/6.6.0/bin/mudrun-headless' -> '6.6.0'."""
return os.path.basename(os.path.dirname(os.path.dirname(bin_path)))
def stop_daemon(run=subprocess.run) -> None:
run(["systemctl", "stop", DAEMON_UNIT], capture_output=True, timeout=20)
def remove_nm_connection(run=subprocess.run) -> None:
"""Mudfish registers a NetworkManager connection for tap0; it is normally removed on stop."""
run(["nmcli", "connection", "delete", "mudfish-tap"], capture_output=True, timeout=10)
def api_base(var_dir: str) -> str:
try:
with open(os.path.join(var_dir, ".ipport")) as f: