diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/netmonitor/__pycache__/__init__.cpython-312.pyc | bin | 159 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/__pycache__/app.cpython-312.pyc | bin | 4846 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/back/__pycache__/flow_features.cpython-312.pyc | bin | 1145 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/back/__pycache__/flow_table.cpython-312.pyc | bin | 9184 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/back/__pycache__/scanner_profile.cpython-312.pyc | bin | 7203 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/back/__pycache__/scanner_profiles_manager.cpython-312.pyc | bin | 12392 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/back/scanner_profile.py | 138 | ||||
| -rw-r--r-- | src/netmonitor/back/scanner_profiles_manager.py | 177 | ||||
| -rw-r--r-- | src/netmonitor/front/__pycache__/options_tab.cpython-312.pyc | bin | 3442 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/front/__pycache__/scanner_profiles_tab.cpython-312.pyc | bin | 6552 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/front/__pycache__/scanner_profiles_tab_pushscreens.cpython-312.pyc | bin | 14133 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/front/__pycache__/scanner_tab.cpython-312.pyc | bin | 14995 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/front/__pycache__/scanner_tab_pushscreens.cpython-312.pyc | bin | 3075 -> 0 bytes | |||
| -rw-r--r-- | src/netmonitor/front/scanner_profiles_tab.py | 84 | ||||
| -rw-r--r-- | src/netmonitor/front/scanner_profiles_tab_pushscreens.py | 180 | ||||
| -rwxr-xr-x | src/netmonitor/front/scanner_tab.py | 277 | ||||
| -rw-r--r-- | src/netmonitor/front/scanner_tab_pushscreens.py | 35 | ||||
| -rw-r--r-- | src/streamml/__init__.py (renamed from src/netmonitor/__init__.py) | 0 | ||||
| -rw-r--r-- | src/streamml/__pycache__/__init__.cpython-312.pyc | bin | 0 -> 155 bytes | |||
| -rw-r--r-- | src/streamml/__pycache__/app.cpython-312.pyc | bin | 0 -> 3493 bytes | |||
| -rw-r--r-- | src/streamml/app.py (renamed from src/netmonitor/app.py) | 20 | ||||
| -rw-r--r-- | src/streamml/back/__pycache__/detector_profile_HST.cpython-312.pyc (renamed from src/netmonitor/back/__pycache__/detector_profile_HST.cpython-312.pyc) | bin | 11545 -> 11541 bytes | |||
| -rw-r--r-- | src/streamml/back/__pycache__/detector_profiles_manager.cpython-312.pyc (renamed from src/netmonitor/back/__pycache__/detector_profiles_manager.cpython-312.pyc) | bin | 10030 -> 10024 bytes | |||
| -rw-r--r-- | src/streamml/back/__pycache__/notification_service.cpython-312.pyc (renamed from src/netmonitor/back/__pycache__/notification_service.cpython-312.pyc) | bin | 2912 -> 2908 bytes | |||
| -rw-r--r-- | src/streamml/back/__pycache__/window.cpython-312.pyc (renamed from src/netmonitor/back/__pycache__/window.cpython-312.pyc) | bin | 9507 -> 9503 bytes | |||
| -rw-r--r-- | src/streamml/back/detector_profile_HST.py (renamed from src/netmonitor/back/detector_profile_HST.py) | 2 | ||||
| -rw-r--r-- | src/streamml/back/detector_profiles_manager.py (renamed from src/netmonitor/back/detector_profiles_manager.py) | 2 | ||||
| -rw-r--r-- | src/streamml/back/notification_service.py (renamed from src/netmonitor/back/notification_service.py) | 0 | ||||
| -rw-r--r-- | src/streamml/back/window.py (renamed from src/netmonitor/back/window.py) | 0 | ||||
| -rw-r--r-- | src/streamml/front/__pycache__/detector_profiles_tab.cpython-312.pyc (renamed from src/netmonitor/front/__pycache__/detector_profiles_tab.cpython-312.pyc) | bin | 5924 -> 5920 bytes | |||
| -rw-r--r-- | src/streamml/front/__pycache__/detector_profiles_tab_pushscreens.cpython-312.pyc (renamed from src/netmonitor/front/__pycache__/detector_profiles_tab_pushscreens.cpython-312.pyc) | bin | 13721 -> 13717 bytes | |||
| -rw-r--r-- | src/streamml/front/__pycache__/detector_tab.cpython-312.pyc (renamed from src/netmonitor/front/__pycache__/detector_tab.cpython-312.pyc) | bin | 7672 -> 7649 bytes | |||
| -rw-r--r-- | src/streamml/front/__pycache__/detector_tab_pushscreens.cpython-312.pyc (renamed from src/netmonitor/front/__pycache__/detector_tab_pushscreens.cpython-312.pyc) | bin | 2798 -> 2794 bytes | |||
| -rw-r--r-- | src/streamml/front/__pycache__/options_tab.cpython-312.pyc | bin | 0 -> 3393 bytes | |||
| -rw-r--r-- | src/streamml/front/detector_profiles_tab.py (renamed from src/netmonitor/front/detector_profiles_tab.py) | 0 | ||||
| -rw-r--r-- | src/streamml/front/detector_profiles_tab_pushscreens.py (renamed from src/netmonitor/front/detector_profiles_tab_pushscreens.py) | 0 | ||||
| -rw-r--r-- | src/streamml/front/detector_tab.py (renamed from src/netmonitor/front/detector_tab.py) | 2 | ||||
| -rw-r--r-- | src/streamml/front/detector_tab_pushscreens.py (renamed from src/netmonitor/front/detector_tab_pushscreens.py) | 0 | ||||
| -rw-r--r-- | src/streamml/front/options_tab.py (renamed from src/netmonitor/front/options_tab.py) | 3 | ||||
| -rw-r--r-- | src/streamml/styles/styles.css (renamed from src/netmonitor/styles/styles.css) | 93 |
40 files changed, 7 insertions, 1006 deletions
diff --git a/src/netmonitor/__pycache__/__init__.cpython-312.pyc b/src/netmonitor/__pycache__/__init__.cpython-312.pyc Binary files differdeleted file mode 100644 index bf05138..0000000 --- a/src/netmonitor/__pycache__/__init__.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/__pycache__/app.cpython-312.pyc b/src/netmonitor/__pycache__/app.cpython-312.pyc Binary files differdeleted file mode 100644 index 38fa57a..0000000 --- a/src/netmonitor/__pycache__/app.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/back/__pycache__/flow_features.cpython-312.pyc b/src/netmonitor/back/__pycache__/flow_features.cpython-312.pyc Binary files differdeleted file mode 100644 index b5e28d0..0000000 --- a/src/netmonitor/back/__pycache__/flow_features.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/back/__pycache__/flow_table.cpython-312.pyc b/src/netmonitor/back/__pycache__/flow_table.cpython-312.pyc Binary files differdeleted file mode 100644 index ffb1702..0000000 --- a/src/netmonitor/back/__pycache__/flow_table.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/back/__pycache__/scanner_profile.cpython-312.pyc b/src/netmonitor/back/__pycache__/scanner_profile.cpython-312.pyc Binary files differdeleted file mode 100644 index 0c8b662..0000000 --- a/src/netmonitor/back/__pycache__/scanner_profile.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/back/__pycache__/scanner_profiles_manager.cpython-312.pyc b/src/netmonitor/back/__pycache__/scanner_profiles_manager.cpython-312.pyc Binary files differdeleted file mode 100644 index f9dc637..0000000 --- a/src/netmonitor/back/__pycache__/scanner_profiles_manager.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/back/scanner_profile.py b/src/netmonitor/back/scanner_profile.py deleted file mode 100644 index 6a20b5b..0000000 --- a/src/netmonitor/back/scanner_profile.py +++ /dev/null @@ -1,138 +0,0 @@ -import os -from pathlib import Path -from datetime import datetime -from tinydb import TinyDB -import nmap -from .notification_service import notification_service - - -XDG_DATA_HOME = Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local/share")) -LOGS_PATH = f"{XDG_DATA_HOME}/netmonitor/scanner/profiles_logs" - -class ScannerProfile: - def __init__(self, profile_name: str, nmap_input=None, scheduler=None, cve=None): - self.profile_name = profile_name - self.nmap_input = nmap_input or {} - self.scheduler = scheduler - self.cve = cve - self.is_active = False - - self.notify_enabled = False - self.notify_only_cve = False - - self.nm = None - self.db = None - self.profile_results_path = f"{LOGS_PATH}/{profile_name}.json" - os.makedirs(os.path.dirname(self.profile_results_path), exist_ok=True) - - @property - def nmap(self): - if self.nm is None: - self.nm = nmap.PortScanner() - return self.nm - - @property - def tinydb(self): - if self.db is None: - self.db = TinyDB(self.profile_results_path) - return self.db - - def __getstate__(self): - state = self.__dict__.copy() - state['nm'] = None - state['db'] = None - return state - - def __setstate__(self, state): - self.__dict__.update(state) - self.nm = None - self.db = None - - def __repr__(self): - return f"<ScannerProfile profile_name={self.profile_name!r}, active={self.is_active}>" - - - def scan(self): - targets = self.nmap_input.get("targets", "") - arguments = self.nmap_input.get("arguments", "") - ports = self.nmap_input.get("ports", "") - - if self.cve: - arguments += " --script=vulners " - - if ports == '': - self.nmap.scan(hosts=targets, arguments=arguments) - else: - self.nmap.scan(hosts=targets, ports=ports, arguments=arguments) - - xml_result = self.nmap.get_nmap_last_output() - analyzed_results = self.nmap.analyse_nmap_xml_scan(xml_result) - - if isinstance(analyzed_results, dict): - analyzed_results['_timestamp'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - - self.tinydb.insert(analyzed_results) - - if self.notify_enabled: - self._handle_notification(analyzed_results, targets) - - return analyzed_results - - def _handle_notification(self, results, targets): - scan_str = str(results).lower() - found_issues = "cve" in scan_str or "vulnerab" in scan_str - should_send = False - msg = f"*Scanner report: {self.profile_name}*\nTargets: `{targets}`" - summary = "" - try: - if 'scan' in results: - for host, data in results['scan'].items(): - summary += f"\n *{host}*" - - if 'tcp' in data: - open_ports = [f"{p}/tcp" for p, info in data['tcp'].items() if info.get('state') == 'open'] - if open_ports: - summary += f"\n Open ports: {', '.join(open_ports)}" - if 'udp' in data: - open_ports = [f"{p}/udp" for p, info in data['udp'].items() if info.get('state') == 'open'] - if open_ports: - summary += f"\n Open ports (UDP): {', '.join(open_ports)}" - if 'osmatch' in data and data['osmatch']: - os_name = data['osmatch'][0].get('name', 'Unknown') - summary += f"\n OS detected: {os_name}" - except Exception as e: - summary += f"\n(Error building summary: {e})" - - if self.notify_only_cve: - if found_issues: - should_send = True - msg += "\nCVE detected!" - msg += "\n---" + summary - else: - should_send = True - msg += "\nScan completed." - if found_issues: - msg += "\nPotential vulnerabilities detected." - - if summary: - msg += "\n---" + summary - - if should_send: - if len(msg) > 1900: - msg = msg[:1900] + "\n...." - notification_service.send_message(msg) - - - def to_dict(self): - return { - "profile_name": self.profile_name, - "nmap_input": self.nmap_input, - "scheduler": self.scheduler, - "is_active": self.is_active, - "notify_enabled": getattr(self, 'notify_enabled', False), - "notify_only_cve": getattr(self, 'notify_only_cve', False), - "results_path": self.profile_results_path, - } - - def get_logs(self): - return self.tinydb.all() diff --git a/src/netmonitor/back/scanner_profiles_manager.py b/src/netmonitor/back/scanner_profiles_manager.py deleted file mode 100644 index 7748835..0000000 --- a/src/netmonitor/back/scanner_profiles_manager.py +++ /dev/null @@ -1,177 +0,0 @@ -import re -from pathlib import Path -from typing import Callable, Literal -from apscheduler.schedulers.background import BackgroundScheduler -from apscheduler.triggers.cron import CronTrigger -import pickle - -from .scanner_profile import ScannerProfile - -SeverityLevel = Literal["information", "warning", "error"] -VALID_NAME_REGEX = r"^[a-zA-Z0-9_-]+$" - -class ScannerProfilesManager: - def __init__(self, profiles_file: str, scheduler: BackgroundScheduler): - self.profiles_file = Path(profiles_file) - self.scheduler = scheduler - self.profiles: list[ScannerProfile] = [] - - self.on_message: Callable[[str, str, str], None] | None = None - self.on_refresh: Callable[[], None] | None = None - - self.load_profiles() - - def _notify(self, msg: str, title: str = "Profile Manager", level: SeverityLevel = "information"): - if self.on_message: - self.on_message(msg, title, level) - - def _refresh_front(self): - if self.on_refresh: - self.on_refresh() - - def _fail(self, msg: str, level: SeverityLevel = "error", notify: bool = True) -> bool: - if notify: - self._notify(msg, level=level) - return False - - def _ok(self, msg: str | None = None, level: SeverityLevel = "information", notify: bool = True) -> bool: - if msg and notify: - self._notify(msg, level=level) - return True - - def try_save_profiles(self, notify: bool = True) -> bool: - try: - self.profiles_file.parent.mkdir(parents=True, exist_ok=True) - with open(self.profiles_file, "wb") as f: - pickle.dump(self.profiles, f) - return self._ok("Profiles saved successfully.", notify=notify) - except Exception as e: - return self._fail(f"Error saving profiles: {e}", notify=notify) - - def load_profiles(self, notify: bool = True) -> bool: - if not self.profiles_file.exists(): - if notify: - self._notify("Profiles file not found. Creating a new one.", level="warning") - if not self.try_save_profiles(notify=False): - return self._fail("Failed to create profiles file!", notify=notify) - return self._ok("New profiles file created.", notify=notify) - - try: - with open(self.profiles_file, "rb") as f: - self.profiles = pickle.load(f) - self._refresh_front() - return self._ok(f"Loaded {len(self.profiles)} profiles.", notify=notify) - except Exception as e: - return self._fail(f"Error loading profiles: {e}", notify=notify) - - - def add_profile(self, profile_name: str, notify: bool = True) -> bool: - if not profile_name: - return self._fail("Name can't be blank.", "error", notify) - - if not re.match(VALID_NAME_REGEX, profile_name): - return self._fail(f"Bad input '{profile_name}'. Use only letters, numbers, '_' and '-'.", "error", notify) - - if any(p.profile_name == profile_name for p in self.profiles): - return self._fail(f"Profile {profile_name} already exists.", "warning", notify) - - new_profile = ScannerProfile(profile_name=profile_name) - self.profiles.append(new_profile) - - if not self.try_save_profiles(notify=False): - self.profiles.remove(new_profile) - return self._fail(f"Failed to save profile {profile_name}.", notify=notify) - - self._refresh_front() - return self._ok(f"Added profile {profile_name}.", notify=notify) - - def delete_profile(self, profile_name: str, notify: bool = True) -> bool: - before = len(self.profiles) - self.profiles = [p for p in self.profiles if p.profile_name != profile_name] - - if len(self.profiles) == before: - return self._fail(f"Profile {profile_name} not found.", "warning", notify) - - if not self.try_save_profiles(notify=False): - return self._fail(f"Failed to save changes after deleting {profile_name}.", notify=notify) - - self._refresh_front() - return self._ok(f"Deleted profile {profile_name}.", notify=notify) - - def get_profile(self, profile_name: str) -> ScannerProfile | None: - return next((p for p in self.profiles if p.profile_name == profile_name), None) - - def update_profile(self, profile_name: str, field: str, value, notify: bool = True) -> bool: - p = self.get_profile(profile_name) - if not p: - return self._fail(f"Profile {profile_name} does not exist.", notify=notify) - - setattr(p, field, value) - if self.try_save_profiles(notify=False): - return self._ok(f"Updated profile {profile_name}.", notify=notify) - else: - return self._fail(f"Failed to save updated profile {profile_name}.", notify=notify) - - - def run_profile_once(self, profile_name: str, notify: bool = True) -> bool: - p = self.get_profile(profile_name) - if not p: - return self._fail(f"Profile {profile_name} not found.", notify=notify) - - try: - p.scan() - return self._ok(f"Scan completed for {profile_name}.", notify=notify) - except Exception as e: - return self._fail(f"Scan error: {e}", notify=notify) - - def turn_on_profile(self, profile_name: str, notify: bool = True) -> bool: - p = self.get_profile(profile_name) - if not p: - return self._fail(f"Profile {profile_name} not found.", notify=notify) - - try: - job_id = f"profile_{p.profile_name}" - self.scheduler.add_job( - lambda: self.run_profile_once(p.profile_name, notify=False), - trigger=CronTrigger.from_crontab(p.scheduler), - id=job_id, - replace_existing=True - ) - p.is_active = True - return self._ok(f"Profile {profile_name} activated.", notify=notify) - except Exception as e: - return self._fail(f"Error activating profile: {e}", notify=notify) - - def turn_off_profile(self, profile_name: str, notify: bool = True) -> bool: - job_id = f"profile_{profile_name}" - try: - self.scheduler.remove_job(job_id) - p = self.get_profile(profile_name) - if p: - p.is_active = False - return self._ok(f"Profile {profile_name} deactivated.", notify=notify) - except Exception as e: - return self._fail(f"Error deactivating profile: {e}", notify=notify) - - def set_validated_scheduler(self, profile_name: str, cron_str: str, notify: bool = True) -> bool: - p = self.get_profile(profile_name) - if not p: - return self._fail(f"Profile {profile_name} not found.", notify=notify) - - try: - CronTrigger.from_crontab(cron_str) - p.scheduler = cron_str - if not self.try_save_profiles(notify=False): - return self._fail(f"Failed to save scheduler for {profile_name}.", notify=notify) - return self._ok(f"Scheduler updated for {profile_name}.", notify=notify) - except ValueError as ve: - return self._fail(f"Invalid CRON: {ve}", notify=notify) - except Exception as e: - return self._fail(f"Unexpected error: {e}", notify=notify) - - def get_profile_logs(self, profile_name: str, notify: bool = True): - p = self.get_profile(profile_name) - if not p: - self._fail(f"Profile {profile_name} not found.", "error", notify) - return None - return p.get_logs() diff --git a/src/netmonitor/front/__pycache__/options_tab.cpython-312.pyc b/src/netmonitor/front/__pycache__/options_tab.cpython-312.pyc Binary files differdeleted file mode 100644 index 227bfa8..0000000 --- a/src/netmonitor/front/__pycache__/options_tab.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/front/__pycache__/scanner_profiles_tab.cpython-312.pyc b/src/netmonitor/front/__pycache__/scanner_profiles_tab.cpython-312.pyc Binary files differdeleted file mode 100644 index d6fcdfb..0000000 --- a/src/netmonitor/front/__pycache__/scanner_profiles_tab.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/front/__pycache__/scanner_profiles_tab_pushscreens.cpython-312.pyc b/src/netmonitor/front/__pycache__/scanner_profiles_tab_pushscreens.cpython-312.pyc Binary files differdeleted file mode 100644 index a4db183..0000000 --- a/src/netmonitor/front/__pycache__/scanner_profiles_tab_pushscreens.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/front/__pycache__/scanner_tab.cpython-312.pyc b/src/netmonitor/front/__pycache__/scanner_tab.cpython-312.pyc Binary files differdeleted file mode 100644 index 8a8d03a..0000000 --- a/src/netmonitor/front/__pycache__/scanner_tab.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/front/__pycache__/scanner_tab_pushscreens.cpython-312.pyc b/src/netmonitor/front/__pycache__/scanner_tab_pushscreens.cpython-312.pyc Binary files differdeleted file mode 100644 index 28cc805..0000000 --- a/src/netmonitor/front/__pycache__/scanner_tab_pushscreens.cpython-312.pyc +++ /dev/null diff --git a/src/netmonitor/front/scanner_profiles_tab.py b/src/netmonitor/front/scanner_profiles_tab.py deleted file mode 100644 index 8e8610c..0000000 --- a/src/netmonitor/front/scanner_profiles_tab.py +++ /dev/null @@ -1,84 +0,0 @@ -from textual.widgets import Button, Label, Switch -from textual import on -from textual.app import ComposeResult -from textual.containers import Vertical, Horizontal, VerticalScroll - -from ..back.scanner_profiles_manager import ScannerProfilesManager -from .scanner_profiles_tab_pushscreens import ScanNowPushScreen, SetSchedulerPushScreen, ShowLogsPushScreen, SetNotifacationOptionsPushScreen, ShowProfilePushScreen, ConfirmDeletePushScreen - -class ScannerProfilesTab(Vertical): - def __init__(self, manager: ScannerProfilesManager, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.manager.on_refresh = self.refresh_profiles - self.manager.on_message = self.on_manager_message - - def compose(self) -> ComposeResult: - yield VerticalScroll(id="profiles-list") - - def on_mount(self) -> None: - self.refresh_profiles() - - def refresh_profiles(self) -> None: - profiles_list = self.query_one("#profiles-list", VerticalScroll) - profiles_list.remove_children() - - if not self.manager.profiles: - return - - for profile in self.manager.profiles: - row = Horizontal( - Switch(id=f"switch-{profile.profile_name}", value=profile.is_active), - Button("Scan Now", id=f"scan-now-button-{profile.profile_name}", classes="profile-action", variant="success"), - Label(f"{profile.profile_name}", classes="profile-profile_name"), - Button("Show Profile", id=f"show-profile-button-{profile.profile_name}", classes="profile-action", variant="primary"), - Button("Show logs", id=f"show-logs-button-{profile.profile_name}", classes="profile-action", variant="default"), - Button("Set scheduler", id=f"set-scheduler-button-{profile.profile_name}", classes="profile-action", variant="default"), - Button("Notifications", id=f"set-notifications-button-{profile.profile_name}", classes="profile-action", variant="default"), - Button("Delete", id=f"delete-{profile.profile_name}", classes="profile-action", variant="error"), - classes="profile-row" - ) - profiles_list.mount(row) - - @on(Switch.Changed) - def switch_changed(self, event: Switch.Changed) -> None: - switch_id = event.switch.id - if not switch_id: - return - profile_name = switch_id.removeprefix("switch-") - - if event.switch.value: - is_turned_on = self.manager.turn_on_profile(profile_name) - if not is_turned_on: - event.switch.value = False - else: - is_turned_off = self.manager.turn_off_profile(profile_name) - if not is_turned_off: - event.switch.value = False - - @on(Button.Pressed) - def on_any_button_pressed(self, event: Button.Pressed) -> None: - button_id = event.button.id - if not button_id: - return - if button_id.startswith("scan-now-button-"): - profile_name = button_id.removeprefix("scan-now-button-") - self.app.push_screen(ScanNowPushScreen(self.manager, profile_name)) - elif button_id.startswith("show-profile-button-"): - profile_name = button_id.removeprefix("show-profile-button-") - self.app.push_screen(ShowProfilePushScreen(self.manager, profile_name)) - elif button_id.startswith("set-scheduler-button-"): - profile_name = button_id.removeprefix("set-scheduler-button-") - self.app.push_screen(SetSchedulerPushScreen(self.manager, profile_name)) - elif button_id.startswith("set-notifications-button-"): - profile_name = button_id.removeprefix("set-notifications-button-") - self.app.push_screen(SetNotifacationOptionsPushScreen(self.manager, profile_name)) - elif button_id.startswith("delete-"): - profile_name = button_id.removeprefix("delete-") - self.app.push_screen(ConfirmDeletePushScreen(self.manager, profile_name)) - elif button_id.startswith("show-logs-button-"): - profile_name = button_id.removeprefix("show-logs-button-") - self.app.push_screen(ShowLogsPushScreen(self.manager, profile_name)) - - def on_manager_message(self, msg: str, title: str, severity): - self.app.notify(message=msg, title=title, severity=severity) diff --git a/src/netmonitor/front/scanner_profiles_tab_pushscreens.py b/src/netmonitor/front/scanner_profiles_tab_pushscreens.py deleted file mode 100644 index 5be9941..0000000 --- a/src/netmonitor/front/scanner_profiles_tab_pushscreens.py +++ /dev/null @@ -1,180 +0,0 @@ -from textual.app import ComposeResult -from textual import on -from textual.screen import ModalScreen -from textual.widgets import Input, Button, Label, Pretty, Select, Switch -from textual.containers import Vertical, Horizontal, VerticalScroll, Container - -from ..back.scanner_profiles_manager import ScannerProfilesManager - -class ScanNowPushScreen(ModalScreen[str]): - def __init__(self, manager: ScannerProfilesManager, profile_name:str, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.profile_name = profile_name - - def compose(self) -> ComposeResult: - with Container(classes="modal-window large-modal"): - yield Label(f"Scanning: {self.profile_name}", classes="modal-header") - with VerticalScroll(classes="info-box"): - yield Pretty(self.manager.get_profile(self.profile_name).scan()) - with Horizontal(classes="modal-footer"): - yield Button("Close", variant="primary") - - @on(Button.Pressed) - async def on_button_pressed(self, event: Button.Pressed) -> None: - self.dismiss(None) - -class ShowProfilePushScreen(ModalScreen[str]): - def __init__(self, manager: ScannerProfilesManager, profile_name:str, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.profile_name = profile_name - - def compose(self) -> ComposeResult: - with Container(classes="modal-window medium-modal"): - yield Label(f"Profile: {self.profile_name}", classes="modal-header") - with VerticalScroll(classes="info-box"): - yield Pretty(self.manager.get_profile(self.profile_name).to_dict()) - with Horizontal(classes="modal-footer"): - yield Button("Close", id="cancel-button", variant="primary") - - @on(Button.Pressed) - async def on_button_pressed(self, event: Button.Pressed) -> None: - self.dismiss(None) - - -class SetSchedulerPushScreen(ModalScreen[str]): - def __init__(self, manager: ScannerProfilesManager, profile_name:str, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.profile_name = profile_name - - def compose(self) -> ComposeResult: - with Container(classes="modal-window small-modal"): - yield Label("Set CRON Scheduler", classes="modal-header") - yield Label("Format: min hour day month day_of_week", classes="label") - yield Input(placeholder="* * * * * ", id="cron-input", classes="input") - - with Horizontal(classes="modal-footer"): - yield Button("Confirm", id="confirm-button", variant="success") - yield Button("Cancel", id="cancel-button", variant="error") - - @on(Button.Pressed) - async def on_button_pressed(self, event: Button.Pressed): - if event.button.id == "confirm-button": - cron_input = self.query_one("#cron-input", Input).value.strip() - if cron_input: - self.manager.set_validated_scheduler(self.profile_name, cron_input) - self.dismiss(None) - else: - self.dismiss(None) - -class SetNotifacationOptionsPushScreen(ModalScreen[str]): - def __init__(self, manager: ScannerProfilesManager, profile_name:str, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.profile_name = profile_name - self.profile = self.manager.get_profile(profile_name) - - def compose(self) -> ComposeResult: - current_enabled = getattr(self.profile, 'notify_enabled', False) - current_cve_only = getattr(self.profile, 'notify_only_cve', False) - - with Container(classes="modal-window small-modal"): - yield Label(f"Notifications: {self.profile_name}", classes="modal-header") - - with Vertical(classes="section-card"): - yield Label("Enable notifications (Discord):") - yield Switch(value=current_enabled, id="switch-enable") - - yield Label("Notify only when scanner finds CVE") - yield Switch(value=current_cve_only, id="switch-cve-only") - - with Horizontal(classes="modal-footer"): - yield Button("Close", id="close-button", variant="primary") - - @on(Switch.Changed) - def on_switch_changed(self, event: Switch.Changed): - if event.switch.id == "switch-enable": - self.profile.notify_enabled = event.value - elif event.switch.id == "switch-cve-only": - self.profile.notify_only_cve = event.value - - self.manager.try_save_profiles(notify=False) - - @on(Button.Pressed) - async def on_button_pressed(self, event: Button.Pressed): - self.dismiss(None) - -class ShowLogsPushScreen(ModalScreen[str]): - def __init__(self, manager: ScannerProfilesManager, profile_name:str, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.profile_name = profile_name - self.logs = [] - - def compose(self) -> ComposeResult: - with Container(classes="modal-window large-modal"): - yield Label(f"Logs: {self.profile_name}", classes="modal-header") - - yield Select([], prompt="Select date", id="scan-date-select") - - with VerticalScroll(classes="info-box"): - yield Pretty({}, id="log-content") - - with Horizontal(classes="modal-footer"): - yield Button("Close", id="cancel-button", variant="primary") - - def on_mount(self): - self.logs = self.manager.get_profile_logs(self.profile_name) - select = self.query_one("#scan-date-select", Select) - options = [] - - if self.logs: - for index, log in enumerate(reversed(self.logs)): - real_index = len(self.logs) - 1 - index - label = log.get('_timestamp', f"Scan #{real_index + 1} (no date)") - - options.append((str(label), real_index)) - - select.set_options(options) - - if options: - select.value = options[0][1] - - @on(Select.Changed, "#scan-date-select") - def on_date_selected(self, event: Select.Changed): - if event.value is not None: - index = event.value - if index == Select.BLANK: - self.query_one("#log-content", Pretty).update({}) - return - if 0 <= index < len(self.logs): - log_entry = self.logs[index] - self.query_one("#log-content", Pretty).update(log_entry) - - @on(Button.Pressed) - async def on_button_pressed(self, event: Button.Pressed) -> None: - self.dismiss(None) - - -class ConfirmDeletePushScreen(ModalScreen[str]): - def __init__(self, manager: ScannerProfilesManager, profile_name:str, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.profile_name = profile_name - - def compose(self) -> ComposeResult: - with Container(classes="modal-window small-modal"): - yield Label("Are you sure?",classes="modal-header") - with Horizontal(classes="modal-footer"): - yield Button("Delete", id="confirm-button", variant="error") - yield Button("Cancel", id="cancel-button", variant="default") - - @on(Button.Pressed) - async def on_button_pressed(self, event: Button.Pressed): - if event.button.id == "confirm-button": - self.manager.delete_profile(self.profile_name) - self.dismiss(None) - else: - self.dismiss(None) diff --git a/src/netmonitor/front/scanner_tab.py b/src/netmonitor/front/scanner_tab.py deleted file mode 100755 index 868fa74..0000000 --- a/src/netmonitor/front/scanner_tab.py +++ /dev/null @@ -1,277 +0,0 @@ -from textual import on
-from textual.app import ComposeResult
-from textual.widgets import Checkbox, Input, Select, Button, Label, SelectionList, Pretty
-from textual.widgets.selection_list import Selection
-from textual.containers import Container, Vertical, Horizontal, VerticalScroll
-from textual.events import Mount
-
-import psutil, ipaddress, shlex
-from typing import List, Dict, Optional
-
-from ..back.scanner_profiles_manager import ScannerProfilesManager
-from .scanner_tab_pushscreens import SaveProfilePushScreen
-
-class ScannerTab(Container):
-
- def __init__(self, manager: ScannerProfilesManager):
- super().__init__()
- self.manager = manager
- self.manager.on_message = self.on_manager_message
-
- def compose(self) -> ComposeResult:
- friendly_section = Container(id="friendly-command-section", classes="section card")
- friendly_section.border_title = "Scanner Configuration"
-
- with friendly_section:
- yield Label("Interface:", classes="label")
- try:
- interfaces = list(psutil.net_if_addrs().keys())
- except Exception:
- interfaces = []
-
- yield Select.from_values(
- interfaces,
- id="interface-select",
- allow_blank=False,
- classes="input"
- )
-
- yield Label("IP address:", classes="label")
- yield Input(
- value="127.0.0.1/32",
- placeholder="192.168.0.0/24",
- name="ip-input",
- id="ip",
- classes="input"
- )
-
- yield Label("Port range (or single port)", classes="label")
- with Horizontal(id="port-range", classes="input-row"):
- yield Input(placeholder="Start / Single", id="low-port-range", classes="input half")
- yield Input(placeholder="End (Optional)", id="high-port-range", classes="input half")
-
- yield Checkbox("Check for CVE's", id="cve-checkbox", classes="checkbox")
-
- yield Label("Scan options:", classes="label")
- with Horizontal(classes="selection-row"):
- yield SelectionList[str](
- Selection("Service version (-sV)", "-sV", False),
- Selection("OS detection (-O)", "-O", False),
- Selection("SYN scan (-sS)", "-sS", False),
- Selection("UDP scan (-sU)", "-sU", False),
- Selection("Fast scan (-F)", "-F", False),
- Selection("Aggressive scan (-A)", "-A", False),
- Selection("Ping skip (-Pn)", "-Pn", False),
- Selection("Timing T4 (-T4)", "-T4", True),
- classes="selection-list"
- )
-
- user_section = Container(id="user-command-section", classes="section card")
- user_section.border_title = "Manual Command"
-
- with user_section:
- yield Input(
- placeholder="sudo nmap -sS 192.168.1.1",
- name="user-nmap-input",
- id="usercommand",
- classes="input full"
- )
-
-
- final_section = Container(id="final-section", classes="section card")
- final_section.border_title = "Execution"
-
- with final_section:
- with Vertical(id="final-command", classes="command-output"):
- self.final_command = Pretty([], id="final-command-output")
- yield self.final_command
- with Vertical(id="buttons", classes="buttons-column"):
- yield Button("Scan now", id="scan-button", variant="success")
- yield Button("Save profile", id="save-button", variant="primary")
-
- results_section = Container(id="results-section", classes="section card")
- results_section.border_title = "Scan Output"
-
- with results_section:
- with VerticalScroll(id="results-scroll"):
- self.results = Pretty([], id="results", classes="results")
- yield self.results
-
- def validate_inputs(self, nmap_input: Dict[str, str]) -> List[str]:
- errors: List[str] = []
-
- if self.query_one("#cve-checkbox", Checkbox).value:
- args = nmap_input.get("arguments", "")
- if "-sV" not in args.split():
- errors.append("To check for CVE's, '-sV' option is required")
- return errors
-
- targets = nmap_input.get("targets", "").strip()
- if not targets:
- errors.append("IP field cannot be empty")
- return errors
-
- if not self.query_one("#usercommand", Input).value.strip():
- try:
- ipaddress.ip_network(targets, strict=False)
- except ValueError:
- errors.append(f"Invalid IP address/CIDR: {targets}")
- return errors
-
- if "ports" in nmap_input:
- port_str = nmap_input["ports"]
- if "-" in port_str:
- try:
- low, high = map(int, port_str.split("-"))
- if not (1 <= low <= 65535 and 1 <= high <= 65535):
- errors.append("Ports must be in range 1-65535")
- if low > high:
- errors.append("Start port cannot be greater than end port")
- except ValueError:
- errors.append("Ports (range) must be numbers")
- else:
- try:
- port = int(port_str)
- if not (1 <= port <= 65535):
- errors.append("Port must be in range 1-65535")
- except ValueError:
- errors.append("Port must be a number")
-
- dry_run_err = self.dry_run_nmap_command(nmap_input)
- if dry_run_err:
- errors.append(dry_run_err)
- return errors
-
- def dry_run_nmap_command(self, nmap_input: Dict[str, str]) -> Optional[str]:
- try:
- cmd = ["nmap"]
- if "arguments" in nmap_input:
- cmd += shlex.split(nmap_input["arguments"])
- if "ports" in nmap_input:
- cmd += ["-p", nmap_input["ports"]]
- cmd.append(nmap_input["targets"])
- return None
- except Exception as e:
- return f"Błąd weryfikacji komendy: {e}"
-
- def get_nmap_input(self, return_dict: bool = False) -> list[str] | dict:
- user_command = self.query_one("#usercommand", Input).value.strip()
- low_port = self.query_one("#low-port-range", Input).value.strip()
- high_port = self.query_one("#high-port-range", Input).value.strip()
- interface = self.query_one("#interface-select", Select).value
- targets = self.query_one("#ip", Input).value.strip()
- options = self.query_one(SelectionList).selected
-
- if return_dict:
- if user_command:
- parts = shlex.split(user_command)
-
- if parts and parts[0] == "sudo": parts.pop(0)
- if parts and parts[0] == "nmap": parts.pop(0)
-
- if not parts:
- return {}
-
- target = parts[-1]
- args = parts[:-1]
-
- return {
- "targets": target,
- "arguments": " ".join(args)
- }
- else:
- nmap_dict = {"targets": targets}
-
- if low_port:
- if high_port:
- nmap_dict["ports"] = f"{low_port}-{high_port}"
- else:
- nmap_dict["ports"] = f"{low_port}"
-
- args: list[str] = []
- if options:
- args.extend(options)
- if interface:
- args.extend(["-e", str(interface)])
- if args:
- nmap_dict["arguments"] = " ".join(args)
-
- return {k: v for k, v in nmap_dict.items() if v is not None}
-
- if user_command:
- return shlex.split(user_command)
-
- parts = ["nmap"]
- if interface:
- parts.extend(["-e", str(interface)])
- if options:
- parts.extend(options)
-
- if low_port:
- if high_port:
- parts.extend(["-p", f"{low_port}-{high_port}"])
- else:
- parts.extend(["-p", f"{low_port}"])
-
- parts.append(targets)
- return parts
-
- @on(Mount)
- @on(SelectionList.SelectedChanged)
- @on(Input.Changed)
- @on(Select.Changed)
- def update_selected_view(self, event=None) -> None:
- self.final_command.update(" ".join(self.get_nmap_input()))
-
- @on(Button.Pressed, "#scan-button")
- async def handle_scan_button(self, event: Button.Pressed) -> None:
- nmap_input = self.get_nmap_input(return_dict=True)
- if not isinstance(nmap_input, dict):
- self.notify("Błąd: dane wejściowe nie są słownikiem", severity="error")
- return
- errors = self.validate_inputs(nmap_input)
- if errors:
- self.notify("\n".join(errors), title="Bad Input", severity="error")
- else:
- try:
- temp_prof_name = "temp_scan_profile"
- self.notify("Start scanning", title="Notification", severity="information")
-
- if not self.manager.add_profile(temp_prof_name, notify=False):
- self.notify("Błąd: Nie udało się utworzyć profilu (problem z zapisem pliku?)", severity="error")
- return
-
- if not self.manager.update_profile(temp_prof_name, "nmap_input", nmap_input, notify=False):
- self.notify("Błąd: Nie udało się zaktualizować parametrów skanowania", severity="error")
- self.manager.delete_profile(temp_prof_name, notify=False)
- return
-
- profile = self.manager.get_profile(temp_prof_name)
- if profile:
- scan_now_results = profile.scan()
- self.results.update(scan_now_results)
- self.manager.delete_profile(temp_prof_name, notify=False)
- self.notify("Scanning completed", title="Notification", severity="information")
- else:
- self.notify("Krytyczny błąd: Profil zniknął po utworzeniu", severity="error")
-
- except Exception as e:
- self.notify(f"Scanner error: {e}", title="Error", severity="error")
-
- @on(Button.Pressed, "#save-button")
- async def handle_save_button(self, event: Button.Pressed):
- nmap_input = self.get_nmap_input(return_dict=True)
- if not isinstance(nmap_input, dict):
- self.notify("Błąd: dane wejściowe nie są słownikiem", severity="error")
- return
-
- errors = self.validate_inputs(nmap_input)
- if errors:
- self.notify("\n".join(errors), title="Bad Input", severity="error")
- return
-
- cve_check = self.query_one("#cve-checkbox", Checkbox).value
- self.app.push_screen(SaveProfilePushScreen(self.manager, nmap_input, cve_check))
-
- def on_manager_message(self, msg: str, title: str, severity):
- self.app.notify(message=msg, title=title, severity=severity)
diff --git a/src/netmonitor/front/scanner_tab_pushscreens.py b/src/netmonitor/front/scanner_tab_pushscreens.py deleted file mode 100644 index 4e4a564..0000000 --- a/src/netmonitor/front/scanner_tab_pushscreens.py +++ /dev/null @@ -1,35 +0,0 @@ -from textual import on -from textual.app import ComposeResult -from textual.widgets import Input, Button, Label -from textual.containers import Vertical, Horizontal -from textual.screen import ModalScreen - -from ..back.scanner_profiles_manager import ScannerProfilesManager - -class SaveProfilePushScreen(ModalScreen[str]): - def __init__(self, manager: ScannerProfilesManager, nmap_input, cve_check, *args, **kwargs): - super().__init__(*args, **kwargs) - self.manager = manager - self.nmap_input = nmap_input - self.cve_check = cve_check - - - def compose(self) -> ComposeResult: - with Vertical(classes="modal-window small-modal"): - yield Label("Save scan profile", classes="modal-header") - yield Input(placeholder="Profile name:", id="profile-name", classes="input") - with Horizontal(id="buttons-row", classes="modal-buttons modal-footer"): - yield Button("Confirm", id="confirm-button", variant="success", classes="button") - yield Button("Cancel", id="cancel-button", variant="error", classes="button") - - @on(Button.Pressed) - async def on_button_pressed(self, event: Button.Pressed): - if event.button.id == "confirm-button": - profile_name = self.query_one("#profile-name", Input).value.strip() - self.manager.add_profile(profile_name) - self.manager.update_profile(profile_name,"nmap_input",self.nmap_input,notify=False) - self.manager.update_profile(profile_name,"cve",self.cve_check, notify=False) - self.dismiss(None) - else: - self.dismiss(None) - diff --git a/src/netmonitor/__init__.py b/src/streamml/__init__.py index e69de29..e69de29 100644 --- a/src/netmonitor/__init__.py +++ b/src/streamml/__init__.py diff --git a/src/streamml/__pycache__/__init__.cpython-312.pyc b/src/streamml/__pycache__/__init__.cpython-312.pyc Binary files differnew file mode 100644 index 0000000..49f5c58 --- /dev/null +++ b/src/streamml/__pycache__/__init__.cpython-312.pyc diff --git a/src/streamml/__pycache__/app.cpython-312.pyc b/src/streamml/__pycache__/app.cpython-312.pyc Binary files differnew file mode 100644 index 0000000..3dcd3e1 --- /dev/null +++ b/src/streamml/__pycache__/app.cpython-312.pyc diff --git a/src/netmonitor/app.py b/src/streamml/app.py index e60108f..4c7d1aa 100644 --- a/src/netmonitor/app.py +++ b/src/streamml/app.py @@ -2,17 +2,13 @@ from textual.app import App, ComposeResult from textual.widgets import TabbedContent, TabPane from textual.theme import Theme -from apscheduler.schedulers.background import BackgroundScheduler from pathlib import Path import os -from .front.scanner_tab import ScannerTab -from .front.scanner_profiles_tab import ScannerProfilesTab from .front.detector_tab import DetectorTab from .front.detector_profiles_tab import DetectorProfilesTab from .front.options_tab import OptionsTab -from .back.scanner_profiles_manager import ScannerProfilesManager from .back.detector_profiles_manager import DetectorProfilesManager @@ -30,25 +26,15 @@ theme = Theme( warning="#ffffba", ) -class NetMonitor(App): +class Streamml(App): CSS_PATH = "styles/styles.css" def __init__(self): super().__init__() - self.scheduler = BackgroundScheduler() - self.scheduler.start() - self.scanner_profiles_manager = ScannerProfilesManager(profiles_file=f"{XDG_DATA_HOME}/netmonitor/objects/scanner_profiles_objects", scheduler=self.scheduler) self.detector_profiles_manager = DetectorProfilesManager(profiles_file=f"{XDG_DATA_HOME}/netmonitor/objects/detector_profiles_objects") def compose(self) -> ComposeResult: with TabbedContent(): - with TabPane(title="Scanner", id="scanner", classes="scanner-theme"): - with TabbedContent(): - with TabPane(title="Scan"): - yield ScannerTab(self.manager.scanner_profiles_manager) - with TabPane(title="Profiles"): - yield ScannerProfilesTab(self.manager.scanner_profiles_manager) - with TabPane(title="Detector", id="detector", classes="detector-theme"): with TabbedContent(): with TabPane(title="Models"): @@ -57,7 +43,7 @@ class NetMonitor(App): yield DetectorProfilesTab(self.manager.detector_profiles_manager) with TabPane(title="Options", id="options", classes="options-theme"): - yield OptionsTab(self.scanner_profiles_manager, self.detector_profiles_manager) + yield OptionsTab(self.detector_profiles_manager) def on_mount(self): self.register_theme(theme) @@ -68,7 +54,7 @@ class NetMonitor(App): return self def main(): - NetMonitor().run() + Streamml().run() if __name__ == "__main__": main() diff --git a/src/netmonitor/back/__pycache__/detector_profile_HST.cpython-312.pyc b/src/streamml/back/__pycache__/detector_profile_HST.cpython-312.pyc Binary files differindex 6dc15c8..72054e8 100644 --- a/src/netmonitor/back/__pycache__/detector_profile_HST.cpython-312.pyc +++ b/src/streamml/back/__pycache__/detector_profile_HST.cpython-312.pyc diff --git a/src/netmonitor/back/__pycache__/detector_profiles_manager.cpython-312.pyc b/src/streamml/back/__pycache__/detector_profiles_manager.cpython-312.pyc Binary files differindex b17c763..598bd22 100644 --- a/src/netmonitor/back/__pycache__/detector_profiles_manager.cpython-312.pyc +++ b/src/streamml/back/__pycache__/detector_profiles_manager.cpython-312.pyc diff --git a/src/netmonitor/back/__pycache__/notification_service.cpython-312.pyc b/src/streamml/back/__pycache__/notification_service.cpython-312.pyc Binary files differindex 71ee4ce..d19dcaa 100644 --- a/src/netmonitor/back/__pycache__/notification_service.cpython-312.pyc +++ b/src/streamml/back/__pycache__/notification_service.cpython-312.pyc diff --git a/src/netmonitor/back/__pycache__/window.cpython-312.pyc b/src/streamml/back/__pycache__/window.cpython-312.pyc Binary files differindex c6971ec..49f5f63 100644 --- a/src/netmonitor/back/__pycache__/window.cpython-312.pyc +++ b/src/streamml/back/__pycache__/window.cpython-312.pyc diff --git a/src/netmonitor/back/detector_profile_HST.py b/src/streamml/back/detector_profile_HST.py index 267b307..6583769 100644 --- a/src/netmonitor/back/detector_profile_HST.py +++ b/src/streamml/back/detector_profile_HST.py @@ -208,7 +208,7 @@ class DetectorProfileHST: return { "is_active": self.is_active, "notify_enabled": self.notify_enabled, - "packets_captured": getattr(self, "packets_read", 0), + "packets_sniffed": getattr(self, "packets_read", 0), "queue_size": self.queue.qsize() if hasattr(self, "queue") and self.queue else 0, "windows_processed": getattr(self, "windows_analyzed", 0), "window_duration": self.window_duration diff --git a/src/netmonitor/back/detector_profiles_manager.py b/src/streamml/back/detector_profiles_manager.py index 1d1c5ea..2f1543c 100644 --- a/src/netmonitor/back/detector_profiles_manager.py +++ b/src/streamml/back/detector_profiles_manager.py @@ -2,7 +2,7 @@ import re from pathlib import Path from typing import Callable, Literal import pickle -from netmonitor.back.detector_profile_HST import DetectorProfileHST +from streamml.back.detector_profile_HST import DetectorProfileHST SeverityLevel = Literal["information", "warning", "error"] diff --git a/src/netmonitor/back/notification_service.py b/src/streamml/back/notification_service.py index e347faf..e347faf 100644 --- a/src/netmonitor/back/notification_service.py +++ b/src/streamml/back/notification_service.py diff --git a/src/netmonitor/back/window.py b/src/streamml/back/window.py index dfa8e7d..dfa8e7d 100644 --- a/src/netmonitor/back/window.py +++ b/src/streamml/back/window.py diff --git a/src/netmonitor/front/__pycache__/detector_profiles_tab.cpython-312.pyc b/src/streamml/front/__pycache__/detector_profiles_tab.cpython-312.pyc Binary files differindex 6a32fac..3e3957b 100644 --- a/src/netmonitor/front/__pycache__/detector_profiles_tab.cpython-312.pyc +++ b/src/streamml/front/__pycache__/detector_profiles_tab.cpython-312.pyc diff --git a/src/netmonitor/front/__pycache__/detector_profiles_tab_pushscreens.cpython-312.pyc b/src/streamml/front/__pycache__/detector_profiles_tab_pushscreens.cpython-312.pyc Binary files differindex a74ee0c..d812190 100644 --- a/src/netmonitor/front/__pycache__/detector_profiles_tab_pushscreens.cpython-312.pyc +++ b/src/streamml/front/__pycache__/detector_profiles_tab_pushscreens.cpython-312.pyc diff --git a/src/netmonitor/front/__pycache__/detector_tab.cpython-312.pyc b/src/streamml/front/__pycache__/detector_tab.cpython-312.pyc Binary files differindex 0257359..ea78d4d 100644 --- a/src/netmonitor/front/__pycache__/detector_tab.cpython-312.pyc +++ b/src/streamml/front/__pycache__/detector_tab.cpython-312.pyc diff --git a/src/netmonitor/front/__pycache__/detector_tab_pushscreens.cpython-312.pyc b/src/streamml/front/__pycache__/detector_tab_pushscreens.cpython-312.pyc Binary files differindex 8672061..798edff 100644 --- a/src/netmonitor/front/__pycache__/detector_tab_pushscreens.cpython-312.pyc +++ b/src/streamml/front/__pycache__/detector_tab_pushscreens.cpython-312.pyc diff --git a/src/streamml/front/__pycache__/options_tab.cpython-312.pyc b/src/streamml/front/__pycache__/options_tab.cpython-312.pyc Binary files differnew file mode 100644 index 0000000..a8a75aa --- /dev/null +++ b/src/streamml/front/__pycache__/options_tab.cpython-312.pyc diff --git a/src/netmonitor/front/detector_profiles_tab.py b/src/streamml/front/detector_profiles_tab.py index 7860e16..7860e16 100644 --- a/src/netmonitor/front/detector_profiles_tab.py +++ b/src/streamml/front/detector_profiles_tab.py diff --git a/src/netmonitor/front/detector_profiles_tab_pushscreens.py b/src/streamml/front/detector_profiles_tab_pushscreens.py index fc5b731..fc5b731 100644 --- a/src/netmonitor/front/detector_profiles_tab_pushscreens.py +++ b/src/streamml/front/detector_profiles_tab_pushscreens.py diff --git a/src/netmonitor/front/detector_tab.py b/src/streamml/front/detector_tab.py index 53dc908..f93a8cb 100644 --- a/src/netmonitor/front/detector_tab.py +++ b/src/streamml/front/detector_tab.py @@ -1,7 +1,7 @@ from textual import on from textual.app import ComposeResult from textual.widgets import Input, Select, Button, Label, Checkbox -from textual.containers import Container, Horizontal, Vertical, VerticalScroll +from textual.containers import Container, Horizontal, VerticalScroll import psutil diff --git a/src/netmonitor/front/detector_tab_pushscreens.py b/src/streamml/front/detector_tab_pushscreens.py index 625921b..625921b 100644 --- a/src/netmonitor/front/detector_tab_pushscreens.py +++ b/src/streamml/front/detector_tab_pushscreens.py diff --git a/src/netmonitor/front/options_tab.py b/src/streamml/front/options_tab.py index 6cbd448..22bd43a 100644 --- a/src/netmonitor/front/options_tab.py +++ b/src/streamml/front/options_tab.py @@ -6,9 +6,8 @@ from textual import on from ..back.notification_service import notification_service class OptionsTab(Container): - def __init__(self, scanner_manager, detector_manager, *args, **kwargs): + def __init__(self, detector_manager, *args, **kwargs): super().__init__(*args, **kwargs) - self.scanner_manager = scanner_manager self.detector_manager = detector_manager def compose(self) -> ComposeResult: diff --git a/src/netmonitor/styles/styles.css b/src/streamml/styles/styles.css index c004b67..25eda16 100644 --- a/src/netmonitor/styles/styles.css +++ b/src/streamml/styles/styles.css @@ -1,96 +1,3 @@ -/* Już sam nie wiem co sie dzieje w tym pliku, ale nie obchodzi mnie to */ -ScannerTab { - layout: grid; - grid-size: 3 5; - grid-gutter: 1; -} - -ScannerTab #friendly-command-section, -ScannerTab #user-command-section, -ScannerTab #results-section { - padding: 1; - border: round $primary; -} - -ScannerTab #friendly-command-section { - row-span: 5; - column-span: 1; -} - -ScannerTab #user-command-section { - row-span: 1; - column-span: 2; -} - -ScannerTab #results-section { - row-span: 3; - column-span: 2; -} - -ScannerTab Label { - padding: 0 1; -} - -ScannerTab Input, -ScannerTab MaskedInput, -ScannerTab Select { - width: 1fr; - margin: 0 0 1 0; -} - -ScannerTab #final-section { - row-span: 1; - column-span: 3; - layout: grid; - grid-size: 3 1; - grid-gutter: 1; - padding: 0; - border: round $primary; -} - -ScannerTab #final-command { - column-span: 2; - padding: 1; - align: center middle; -} - -ScannerTab #final-command-output { - border: solid $secondary; - overflow: auto; -} - -ScannerTab #buttons { - column-span: 1; - layout: vertical; - align: center middle; - border-left: solid $primary 20%; -} - -ScannerTab #buttons Button { - width: 90%; - padding: 1; -} - -ScannerTab #scan-button { - border: none; -} - -ScannerTab #save-button { - border: none; -} - - - -ScannerTab #results-scroll { - height: 1fr; - width: 100%; - scrollbar-color: $primary ; - scrollbar-background: $background; - scrollbar-size-horizontal: 1; -} - - - DetectorTab Button { content-align: center middle; } |