from __future__ import annotations import json import shutil import subprocess import sys from pathlib import Path def pymobiledevice3_binary() -> str: sibling = Path(sys.executable).with_name("pymobiledevice3") if sibling.is_file(): return str(sibling) discovered = shutil.which("pymobiledevice3") if discovered is None: raise RuntimeError("pymobiledevice3 is not installed in this environment") return discovered def pymobiledevice3_version(binary: str) -> str: completed = subprocess.run( [binary, "--no-color", "version"], check=False, capture_output=True, text=True, timeout=20, ) if completed.returncode != 0: raise RuntimeError("pymobiledevice3 version check failed") return completed.stdout.strip() def usb_device_count(binary: str) -> int: completed = subprocess.run( [binary, "--no-color", "usbmux", "list", "--usb"], check=False, capture_output=True, text=True, timeout=20, ) if completed.returncode != 0: raise RuntimeError( "USB discovery failed; unlock the iPhone and confirm Trust This Computer" ) try: payload = json.loads(completed.stdout) except json.JSONDecodeError as exc: raise RuntimeError("USB discovery returned an unexpected response") from exc if not isinstance(payload, list): raise RuntimeError("USB discovery returned an unexpected response") return len(payload) def main() -> int: try: binary = pymobiledevice3_binary() version = pymobiledevice3_version(binary) count = usb_device_count(binary) except (OSError, RuntimeError, subprocess.SubprocessError) as exc: print(f"BLOCKED: {exc}") return 2 print(f"pymobiledevice3: {version}") print(f"USB iPhone devices: {count}") if count == 0: print("BLOCKED: connect one unlocked iPhone with a data cable and confirm Trust") return 2 if count > 1: print("BLOCKED: leave exactly one trusted iPhone connected for a redacted capture") return 2 print("READY: one trusted USB iPhone is available; no device identifier was printed") return 0 if __name__ == "__main__": raise SystemExit(main())