diff --git a/.github/release-notes.md b/.github/release-notes.md index 88645a0..dc786cb 100644 --- a/.github/release-notes.md +++ b/.github/release-notes.md @@ -13,6 +13,10 @@ The source archive is the same tree a clone would have: unzip it and run `./start.sh` (Linux/macOS) or `start.bat` (Windows). Direct SIMtrace2 capture on Linux additionally needs the attached `70-simtrace2-pysniff.rules` udev rule. +The `.sh` launchers are for Linux/macOS only: on Windows use `start.bat` / +`sniff-start.bat` from `cmd.exe` or PowerShell (WSL, Git Bash, MSYS2, MinGW and +Cygwin are refused). + **Runtime zip (no installer)** — `simtrace-analyser-*.zip` is the runtime tree only (packages, PWA, launchers, docs — no tests, no git): extract it anywhere and run `start.bat` (Windows) or `./start.sh` diff --git a/README.md b/README.md index 60c6d5a..e677ab7 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ http://127.0.0.1:8081/. The wheel includes the UI, so the server serves it by itself: ```sh -pip install ./simtrace_analyser-2.7.13-py3-none-any.whl +pip install ./simtrace_analyser-2.7.14-py3-none-any.whl simtrace-analyser-server --capture gsmtap ``` @@ -61,7 +61,7 @@ Every artifact is on the CLI can pick the latest one: ```sh -pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.13/simtrace_analyser-2.7.13-py3-none-any.whl +pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.14/simtrace_analyser-2.7.14-py3-none-any.whl # or: gh release download --pattern '*.whl' pip install ./simtrace_analyser-*.whl @@ -69,7 +69,7 @@ pip install ./simtrace_analyser-*.whl ### 2. Zip (no installer) -Download `simtrace-analyser-2.7.13.zip` from the release page and extract it +Download `simtrace-analyser-2.7.14.zip` from the release page and extract it anywhere: it is the runtime tree (the Python packages, the web UI, the launchers and the docs — no tests, no git). The archive works on any OS; then run: @@ -167,6 +167,11 @@ start.bat --capture direct start.bat --capture disabled ``` +On Windows use `start.bat` / `sniff-start.bat` from `cmd.exe` or PowerShell: +the `.sh` launchers refuse to run in WSL (the Linux guest cannot reach the +Windows SIMtrace2 USB device) and in Git Bash / MSYS2 / MinGW / Cygwin (no +Linux `/sys` + `/dev/bus/usb` view for the udev checks). + Options pass through unchanged (`./start.sh --capture direct --port 8080`). The server logs its capture liveness to stderr (each line timestamped diff --git a/README_RUS.md b/README_RUS.md index a20dc15..ae349f7 100644 --- a/README_RUS.md +++ b/README_RUS.md @@ -47,7 +47,7 @@ http://127.0.0.1:8081/. Wheel содержит интерфейс внутри пакета, поэтому сервер отдаёт его сам: ```sh -pip install ./simtrace_analyser-2.7.13-py3-none-any.whl +pip install ./simtrace_analyser-2.7.14-py3-none-any.whl simtrace-analyser-server --capture gsmtap ``` @@ -61,7 +61,7 @@ Fedora), сначала создайте виртуальное окружени CLI — выбрать последнюю: ```sh -pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.13/simtrace_analyser-2.7.13-py3-none-any.whl +pip install https://github.com/anttro/simtrace-analyser/releases/download/v2.7.14/simtrace_analyser-2.7.14-py3-none-any.whl # или: gh release download --pattern '*.whl' pip install ./simtrace_analyser-*.whl @@ -69,7 +69,7 @@ pip install ./simtrace_analyser-*.whl ### 2. Zip (без установки) -Скачайте `simtrace-analyser-2.7.13.zip` со страницы релиза и распакуйте в любое +Скачайте `simtrace-analyser-2.7.14.zip` со страницы релиза и распакуйте в любое место: это рабочее дерево (пакеты Python, интерфейс, скрипты запуска и документация — без тестов и git). Архив подходит для любой ОС. Затем запустите. @@ -169,6 +169,11 @@ start.bat --capture direct start.bat --capture disabled ``` +В Windows запускайте `start.bat` / `sniff-start.bat` из `cmd.exe` или +PowerShell: `.sh`-скрипты отказываются работать в WSL (гостевая Linux-система +не видит USB-устройство SIMtrace2) и в Git Bash / MSYS2 / MinGW / Cygwin (нет +Linux-представления `/sys` + `/dev/bus/usb` для проверок udev). + Параметры передаются как есть (`./start.sh --capture direct --port 8080`). Сервер пишет в stderr информацию о жизненном цикле захвата (каждая строка diff --git a/frontend/index.html b/frontend/index.html index 83a2718..3b50345 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3389,7 +3389,7 @@ function onSearchChange() { } // ──────────────────── Versioning ──────────────────── -const PWA_VERSION = '2.7.13'; +const PWA_VERSION = '2.7.14'; const MIN_SERVER_VERSION = '2.3.0'; function parseVersion(v) { diff --git a/frontend/sw.js b/frontend/sw.js index 4e68b5d..03997a8 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simtrace-analyser-v95'; +const CACHE = 'simtrace-analyser-v96'; const PRECACHE = [ 'index.html', diff --git a/pyproject.toml b/pyproject.toml index 1e30800..11a0210 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "simtrace-analyser" -version = "2.7.13" +version = "2.7.14" description = "SIMtrace Analyser — APDU trace analyser for GSMTAP-SIM, SIMtrace2, PCAP/PCAPNG and COMPRION captures (bundles the simtrace2-pysniff utility)" readme = {file = "README.md", content-type = "text/markdown"} license = "MIT" diff --git a/simtrace_analyser/version.py b/simtrace_analyser/version.py index 06c51a7..77dc045 100644 --- a/simtrace_analyser/version.py +++ b/simtrace_analyser/version.py @@ -1,3 +1,3 @@ """Single source of truth for the SIMtrace Analyser version.""" -__version__ = '2.7.13' +__version__ = '2.7.14' diff --git a/sniff-start.sh b/sniff-start.sh index a464121..ed22010 100755 --- a/sniff-start.sh +++ b/sniff-start.sh @@ -8,6 +8,20 @@ set -euo pipefail shopt -s nullglob +# Windows guard: sniff-start.sh is the native Linux/macOS launcher. Under WSL +# the Linux guest cannot reach the Windows SIMtrace2 USB device, and a Git Bash / +# MSYS2 / MinGW / Cygwin shell has no Linux /sys + /dev/bus/usb view for the +# permission pre-flight below. Use sniff-start.bat from cmd.exe or PowerShell, +# which drives the Windows Python/PyUSB stack. A deliberate WSL/Cygwin flow can +# run `python -m simtrace2_pysniff` directly. +if grep -qi microsoft /proc/version 2>/dev/null || \ + uname -s 2>/dev/null | grep -qiE 'MINGW|MSYS|CYGWIN'; then + echo "Error: sniff-start.sh is the Linux/macOS helper and cannot run on Windows" >&2 + echo "(WSL / MSYS2 / MinGW / Cygwin detected)." >&2 + echo "Use sniff-start.bat from a Windows command prompt (cmd.exe / PowerShell) instead." >&2 + exit 2 +fi + PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" GSMTAP="${GSMTAP:-}" diff --git a/start.sh b/start.sh index 422feb2..0466b97 100755 --- a/start.sh +++ b/start.sh @@ -8,6 +8,20 @@ set -euo pipefail shopt -s nullglob +# Windows guard: start.sh is the native Linux/macOS launcher. Under WSL the +# Linux guest cannot reach the Windows SIMtrace2 USB device, and a Git Bash / +# MSYS2 / MinGW / Cygwin shell has no Linux /sys + /dev/bus/usb view for the +# udev pre-flight below. Use start.bat from cmd.exe or PowerShell, which drives +# the Windows Python/PyUSB stack. A deliberate WSL/Cygwin flow can run +# `python -m simtrace_analyser` directly. +if grep -qi microsoft /proc/version 2>/dev/null || \ + uname -s 2>/dev/null | grep -qiE 'MINGW|MSYS|CYGWIN'; then + echo "Error: start.sh is the Linux/macOS helper and cannot run on Windows" >&2 + echo "(WSL / MSYS2 / MinGW / Cygwin detected)." >&2 + echo "Use start.bat from a Windows command prompt (cmd.exe / PowerShell) instead." >&2 + exit 2 +fi + PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" CAPTURE="${CAPTURE:-gsmtap}" diff --git a/tests/test_launchers.py b/tests/test_launchers.py new file mode 100644 index 0000000..ef2964f --- /dev/null +++ b/tests/test_launchers.py @@ -0,0 +1,71 @@ +"""Tests for the bash launchers' Windows-hosted-shell guard.""" + +import os +import shutil +import stat +import subprocess +import tempfile +import unittest +from pathlib import Path + +REPO = Path(__file__).resolve().parents[1] +BASH = shutil.which('bash') + +LAUNCHERS = ( + ('start.sh', 'start.bat'), + ('sniff-start.sh', 'sniff-start.bat'), +) + + +@unittest.skipUnless(BASH, 'bash is not installed') +class TestWindowsGuard(unittest.TestCase): + def _run_as_windows(self, script): + """Run *script* with a fake `uname -s` naming a mingw host.""" + with tempfile.TemporaryDirectory() as tmp: + fake = Path(tmp) / 'uname' + fake.write_text('#!/bin/sh\necho MINGW64_NT-10.0\n') + fake.chmod(0o755) + env = dict(os.environ) + env['PATH'] = tmp + os.pathsep + env.get('PATH', '') + return subprocess.run( + [BASH, str(REPO / script)], cwd=REPO, env=env, + capture_output=True, text=True, timeout=30) + + def test_guard_exits_and_names_the_bat_launcher(self): + for script, bat in LAUNCHERS: + with self.subTest(script=script): + res = self._run_as_windows(script) + self.assertEqual(res.returncode, 2, res.stderr) + self.assertIn( + 'Error: %s is the Linux/macOS helper and cannot run on ' + 'Windows' % script, res.stderr) + self.assertIn( + '(WSL / MSYS2 / MinGW / Cygwin detected).', res.stderr) + self.assertIn( + 'Use %s from a Windows command prompt (cmd.exe / ' + 'PowerShell) instead.' % bat, res.stderr) + + def test_guard_detects_wsl_and_native_windows_shells(self): + # The mingw/msys/cygwin branch is exercised above; pin the WSL branch + # and the exit code so a refactor cannot drop either detection. + for script, _ in LAUNCHERS: + with self.subTest(script=script): + src = (REPO / script).read_text() + self.assertIn('grep -qi microsoft /proc/version', src) + self.assertIn('MINGW|MSYS|CYGWIN', src) + self.assertIn('exit 2', src) + self.assertLess(src.index('Windows guard'), + src.index('PROJECT_DIR='), + 'the guard must run before the launcher setup') + + def test_shell_syntax(self): + for script, _ in LAUNCHERS: + with self.subTest(script=script): + res = subprocess.run( + [BASH, '-n', str(REPO / script)], + capture_output=True, text=True) + self.assertEqual(res.returncode, 0, res.stderr) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_pcap_import.py b/tests/test_pcap_import.py index c826c4b..a23fe90 100644 --- a/tests/test_pcap_import.py +++ b/tests/test_pcap_import.py @@ -224,7 +224,7 @@ class TestImportEndpoint(unittest.TestCase): class TestVersion(unittest.TestCase): def test_package_version(self): from simtrace2_pysniff import __version__ - self.assertEqual(__version__, '2.7.13') + self.assertEqual(__version__, '2.7.14') def test_status_includes_version(self): import os