Adds a new default plugin that provides a web UI for browsing,
downloading, and analyzing captured WiFi handshakes and network data.
Features:
- Browse and search captured .pcap handshake files
- Download individual files or all as a zip archive
- Interactive network map with D3.js force-directed graph
- Zoom, pan, drag nodes to rearrange
- AP nodes colored by encryption type, sized by client count
- Click AP to highlight its connected clients
- Auto-fits to viewport after layout settles
- Sortable table view with expandable AP rows showing clients
- Handshake column with download links for captured .pcap files
- Historical AP import from existing pcap filenames
- Live data from bettercap session merged with persistent history
- Stats bar: AP count, unique clients, total data volume
- Persistent JSON storage surviving reboots
Add _IFACE_RE regex and _validate_iface() classmethod that validates
Linux network interface names (max 15 chars, alphanumeric plus dash
and underscore). Provides a safety net against malformed names if
interface configuration is ever externalized.
on_epoch and on_bcap_sys_log run from different threads (main loop vs
bettercap event handler). Both read and write self.LASTTRY without
synchronization, creating a race where two recovery actions fire
simultaneously. Similarly, isReloadingMon can be checked and set by
concurrent threads leading to overlapping restarts.
Add a threading.Lock to serialize cooldown checks and state mutations:
- on_bcap_sys_log: lock around LASTTRY cooldown check
- on_epoch: lock around LASTTRY cooldown check
- _tryTurningItOffAndOnAgain: lock around duplicate-attempt guard,
early return instead of else-block to flatten indentation
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
Patterns 5 (concurrent map iteration) and 6 (panic: runtime error) had
identical handlers — both log "Bettercap has crashed!", restart bettercap,
and restart pwnagotchi. Merge into a single elif with an or condition.
Closes#539
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
Plugin code uses print() in several places instead of the logging
module. On a headless Pi Zero, print() output goes nowhere useful
while logging integrates with pwnagotchi's log system.
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
'"success" in result' checks if the key exists in the dict (always
True for valid responses), not whether the operation succeeded.
result["success"] can KeyError if the key is missing.
Change all checks to result.get("success") which correctly returns
the boolean value or None if the key is absent.
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>