110 lines
4.4 KiB
Python
110 lines
4.4 KiB
Python
import wx
|
|
import wx.adv as adv
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class ScanWizardResultsPage(adv.WizardPageSimple):
|
|
def __init__(self, parent, scan_handler, main_frame):
|
|
super().__init__(parent)
|
|
self.scan_handler = scan_handler
|
|
self.main_frame = main_frame
|
|
self.discovered = []
|
|
self._build_ui()
|
|
|
|
def _build_ui(self):
|
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
self.summary = wx.StaticText(self, label="Waiting to start…")
|
|
sizer.Add(self.summary, 0, wx.ALL, 5)
|
|
|
|
self.gauge = wx.Gauge(self, range=100, style=wx.GA_SMOOTH)
|
|
sizer.Add(self.gauge, 0, wx.EXPAND | wx.ALL, 5)
|
|
|
|
self.results_list = wx.ListCtrl(self, style=wx.LC_REPORT | wx.BORDER_SUNKEN)
|
|
self.results_list.InsertColumn(0, "Address", width=140)
|
|
self.results_list.InsertColumn(1, "Port", width=60)
|
|
self.results_list.InsertColumn(2, "Details", width=260)
|
|
self.results_list.Bind(wx.EVT_LIST_ITEM_SELECTED, self._toggle_buttons)
|
|
self.results_list.Bind(wx.EVT_LIST_ITEM_DESELECTED, self._toggle_buttons)
|
|
sizer.Add(self.results_list, 1, wx.EXPAND | wx.ALL, 5)
|
|
|
|
btn_row = wx.BoxSizer(wx.HORIZONTAL)
|
|
self.quick_connect_btn = wx.Button(self, label="Quick Connect")
|
|
self.quick_connect_btn.Disable()
|
|
self.quick_connect_btn.Bind(wx.EVT_BUTTON, self.on_quick_connect)
|
|
btn_row.Add(self.quick_connect_btn, 0, wx.RIGHT, 5)
|
|
|
|
self.rescan_btn = wx.Button(self, label="Rescan")
|
|
self.rescan_btn.Bind(wx.EVT_BUTTON, self.on_rescan)
|
|
btn_row.Add(self.rescan_btn, 0)
|
|
sizer.Add(btn_row, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
|
|
|
|
self.SetSizer(sizer)
|
|
|
|
def prepare_for_scan(self, params, start_callback):
|
|
self.results_list.DeleteAllItems()
|
|
self.discovered = []
|
|
self.summary.SetLabel(f"Scanning {params['cidr']} on ports {', '.join(map(str, params['ports']))}…")
|
|
self.gauge.SetRange(max(params["host_count"], 1))
|
|
self.gauge.SetValue(0)
|
|
self.quick_connect_btn.Disable()
|
|
start_callback(params)
|
|
|
|
def on_scan_progress(self, scanned, total):
|
|
try:
|
|
total = max(total, 1)
|
|
self.gauge.SetRange(total)
|
|
self.gauge.SetValue(min(scanned, total))
|
|
self.summary.SetLabel(f"Scanning… {scanned}/{total} hosts checked")
|
|
except RuntimeError:
|
|
# C++ SHIT
|
|
logger.debug("Scan progress update after controls destroyed; ignoring")
|
|
|
|
def on_scan_result(self, server_info):
|
|
"""Handle a single discovered server row."""
|
|
try:
|
|
idx = self.results_list.InsertItem(self.results_list.GetItemCount(), server_info["address"])
|
|
self.results_list.SetItem(idx, 1, str(server_info["port"]))
|
|
self.results_list.SetItem(idx, 2, server_info.get("banner", "IRC server detected"))
|
|
self.discovered.append(server_info)
|
|
self.summary.SetLabel(
|
|
f"Found {len(self.discovered)} {'server' if len(self.discovered) == 1 else 'servers'}"
|
|
)
|
|
except RuntimeError:
|
|
logger.debug("Scan result update after controls destroyed; ignoring")
|
|
|
|
def on_scan_complete(self, results):
|
|
"""Final scan completion callback."""
|
|
try:
|
|
if results:
|
|
self.summary.SetLabel(
|
|
f"Scan complete : {len(results)} "
|
|
f"{'server' if len(results) == 1 else 'servers'} ready."
|
|
)
|
|
else:
|
|
self.summary.SetLabel("Scan complete : no IRC servers discovered.")
|
|
self._toggle_buttons()
|
|
except RuntimeError:
|
|
logger.debug("Scan completion update after controls destroyed; ignoring")
|
|
|
|
def on_quick_connect(self, event):
|
|
row = self.results_list.GetFirstSelected()
|
|
if row == -1:
|
|
return
|
|
server = self.results_list.GetItemText(row, 0)
|
|
port = int(self.results_list.GetItemText(row, 1))
|
|
if self.main_frame.quick_connect(server, port):
|
|
self.GetParent().EndModal(wx.ID_OK)
|
|
|
|
def on_rescan(self, event):
|
|
wizard = self.GetParent()
|
|
wizard.ShowPage(wizard.intro_page)
|
|
|
|
def _toggle_buttons(self, event=None):
|
|
has_selection = self.results_list.GetFirstSelected() != -1
|
|
if has_selection:
|
|
self.quick_connect_btn.Enable()
|
|
else:
|
|
self.quick_connect_btn.Disable()
|