1. Overview
The Samba Scanning module provides configuration and on-demand scanning of SMB/Samba network paths. It allows the user to:
- Enable or disable Samba scanning globally
- Maintain a list of SMB paths to scan
- Store optional SMB credentials per path (handled by the backend)
- Trigger a manual scan session with real-time progress feedback
- Stop an active scan via explicit user action
The module is implemented as a GTKmm (GTK4) page and relies on the Backend singleton for configuration persistence and scanning orchestration.
2. User Interface Structure
2.1 Enable/Disable Switch
The page provides a top-level switch (switchEnable) to enable or disable Samba scanning. The label is rendered using markup:
<b>Enable Samba scanning</b>
The switch is bound to signal_state_set(). Configuration is persisted only when the UI is not in a loading phase (guarded by loading_), preventing unintended saves during initialization.
2.2 Directories Table
Configured SMB paths are displayed in a Gtk::TreeView backed by a Gtk::ListStore model:
- Model:
sambaStore - View:
sambaView - Primary column: “Path” mapped to
sambaCols.col_path
The view is placed in a scrolled container to support long lists.
2.3 Action Buttons
The bottom action bar contains the following buttons:
- Add (
btnAdd) – add a new SMB path - Remove (
btnRemove) – remove the selected SMB path - Scan Now (
btnScan) – start a scanning session - Save Configuration (
btnSave) – persist the current configuration explicitly
The “Scan Now” button is enabled only when:
- Samba scanning is enabled
- At least one SMB path exists in the model
3. Configuration Load and Save
3.1 Loading Configuration
Configuration is loaded via loadConfig(), which:
- Sets
loading_ = trueto suppress auto-save triggers - Clears the list store
- Loads the enable state from
Backend::instance().isSambaEnabled() - Populates the list store using
Backend::instance().getSambaDirs() - Resets
loading_ = false
3.2 Saving Configuration
Configuration is saved via saveConfig(), which:
- Extracts all non-empty SMB paths from the list store
- Calls
Backend::instance().saveSambaConfig(enabled, dirs) - Refreshes UI enable/disable logic (
refreshUI()) - Shows a confirmation dialog to the user
4. Adding an SMB Path
4.1 Custom Dialog
The “Add” flow uses a custom, non-modal GTK dialog with BastionGuard styling (custom header bar, close icon, and themed CSS classes). The dialog collects:
- SMB URL:
smb://server/share/path - Username (optional)
- Password (optional, hidden input)
4.2 URL Normalization and Validation
When the user confirms, the SMB URL is normalized by the backend helper:
url = Backend::resolveSambaDir(url)
Then it is normalized further by:
- Replacing backslashes with slashes
- Removing trailing
/(except root-level cases)
Validation is enforced via:
Backend::isValidSMB(url)
If invalid, an error dialog is shown and the entry is not added.
4.3 Credential Storage
If the entry is valid, the module stores credentials through the backend:
Backend::instance().saveSMBCredentials(url, user, pass)
The UI then calls saveConfig() to persist the updated path list.
5. Removing an SMB Path
The “Remove” button deletes the selected row from the tree view model and then persists configuration by calling saveConfig().
6. Manual Samba Scan Session
6.1 Session Initialization
When “Scan Now” is clicked, the module:
- Resets any existing stop request state using
Backend::instance().resetSambaStop() - Creates shared state flags (
activeanddialog_open) to coordinate UI lifecycle - Builds a custom non-modal scan dialog (header + progress + file list)
6.2 Scan Dialog Components
The scan dialog includes:
- A centered title label reporting scan status and completion summary
- A “Current file” label updated continuously
- A progress bar configured with percent text
- A list box used to display scanned file entries / scan log lines
- Two buttons:
- Stop Scan – requests stop and closes the dialog
- Close – closes the dialog (also triggers stop request on close request)
6.3 UI Refresh Timer (250ms)
During the scan session, the dialog is updated every 250ms using a GLib timeout. The timer callback reads scan state from the backend via:
Backend::instance().get_current_scan_files()
The scan state is expected to include:
scan_active– whether scanning is still runningcurrent_scanning– current file being scannedprogress– float progress fraction (0..1)files– a list of processed/log entries to renderinfected– count of infected items
If scanning completes (scan_active == false), the dialog transitions to a completion state and shows a summary including total files and infected files.
6.4 Stop and Close Behavior
The stop button requests a scan stop using:
Backend::instance().requestStopSambaScan()
On window close request, the module:
- Marks the dialog as closed (
*dialog_open = false) - Disconnects the refresh timer
- Requests scan stop via the backend
6.5 Backend Progress Callback
The page registers a backend callback for progress summary updates:
Backend::instance().samba_progress_callback = ...
The callback schedules UI updates using Glib::signal_idle().connect_once() to ensure GTK thread safety.
6.6 Scan Execution Thread
Actual scanning is executed in a detached thread. The module retrieves configured SMB paths via:
Backend::instance().getSambaDirs()
Each directory is scanned by calling:
Backend::instance().scanSambaDir(d)
This keeps the UI responsive while the backend performs remote scanning and result collection.
7. Runtime and Security Considerations
- Non-modal scanning UI: the scan dialog does not block the rest of the application.
- UI-safe updates: periodic refresh and backend callbacks use GLib scheduling to avoid GTK calls from worker threads.
- Manual remediation notice: the add-path dialog explicitly informs the user that malware removal on remote SMB files may require manual intervention.
- Stop control: the module includes explicit stop mechanics integrated with backend stop flags, preventing long-running scan sessions from becoming unmanageable.