Skip to content
API Documentation
BastionGuard™
SettingsPage Class Reference

#include <SettingsPage.hpp>

Inheritance diagram for SettingsPage:

Classes

struct  SambaColumns
class  RuleColumns
class  PhishColumns
struct  AllowlistCols

Public Member Functions

 SettingsPage (ClamdConfig &config)
 ~SettingsPage () override
void goto_page (int n)
void set_notebook_no_tabs ()
 SettingsPage ()
void setProtectionEnabled (bool enabled)
void setSystemIntegrationStatus (const std::string &text)
void refreshState ()
sigc::signal< void(bool)> & signal_toggle_protection_requested ()

Private Member Functions

void build_secure_payments_tab ()
void build_proxy_bypass_tab ()
void build_clamav_db_tab ()
void refresh_clamav_db_list (Gtk::Box *listBox)
void build_email_security_tab ()
void onAddSambaDir ()
void onRemoveSambaDir ()
void onScanNowSamba ()
bool validate_samba_dirs ()
std::vector< std::string > collect_samba_dirs (const Glib::RefPtr< Gtk::ListStore > &store, const SambaColumns &cols)
void onQuarantineClicked ()
void onAddPath ()
void onRemovePath ()
void onSave ()
void onRealtimeToggled ()
void build_antiransom_tab ()
void build_antiransom_advanced_tab ()
void loadAdvancedConfig ()
void loadAllowlistUI ()
void saveAllowlistUI ()
void saveAdvancedConfig (bool suspicious_only, const Glib::ustring &ignore_paths, const Glib::ustring &ignore_ext, const Glib::ustring &suspicious_ext)
void onAntiransomToggled ()
void refreshAntiransomRules ()
void loadYaraRules ()
void loadScannerConfig (bool &use_rules, bool &use_db, int &interval, std::vector< std::string > &dirs)
void saveScannerConfig (bool use_rules, bool use_db, int interval, const std::vector< std::string > &dirs)
void build_antiphish_tab ()
void onAntiphishToggled ()
void refreshPhishLists ()
void loadPhishLists ()
void build_options_tab ()
void build_whitelist_tab ()
void build_user_services_tab ()
bool is_user_service_enabled (const std::string &service_name)
bool enable_user_service (const std::string &service_name)
bool disable_user_service (const std::string &service_name)
bool is_system_service_enabled (const std::string &unit_name)
bool enable_system_service (const std::string &unit_name)
bool disable_system_service (const std::string &unit_name)
bool run_cmd (const std::vector< std::string > &argv, std::string *out_stdout=nullptr, bool silence_stderr=true)
bool pkexec_servicectl (const std::vector< std::string > &args, std::string *out_stdout=nullptr)
void build_services_section (Gtk::Box &parent, const std::vector< std::tuple< std::string, Glib::ustring, Glib::ustring > > &services, bool system_units)
void build_system_services_tab ()
void buildUi ()
void loadPreference ()
bool serviceEnabled () const
bool autostartInstalled () const
bool backupExists () const

Static Private Member Functions

static void show_service_error_dialog (const Glib::ustring &message, const std::string &service_name)
static std::string boolText (bool value)

Private Attributes

ClamdConfig & clamdConfig
Gtk::Stack stack
Gtk::StackSwitcher stack_switcher
std::vector< Gtk::Widget * > page_order_
Gtk::Switch clamonaccSwitch
Gtk::Label realtimeLabel
Gtk::Label quarantineLabel
Gtk::Button quarantineButton
Gtk::ListBox listbox_paths
Gtk::Button btn_addPath
Gtk::Button btn_removePath
Gtk::Box box_scanOptions {Gtk::Orientation::VERTICAL}
std::map< std::string, Gtk::CheckButton * > checkOptions
Gtk::Switch toggleAllSwitch
Gtk::Label toggleAllLabel
Gtk::Button btn_save
Gtk::Button btn_applyBase
Gtk::Label * clamdb_count_label_ = nullptr
Gtk::ComboBoxText combo_os_
Gtk::Entry entry_http_port_
Gtk::Entry entry_https_port_
bool http_updating_ = false
bool https_updating_ = false
Gtk::Button btn_apply_webconfig_
Gtk::Switch antiransomSwitch
Gtk::Label antiransomStatus
RuleColumns ruleCols
Glib::RefPtr< Gtk::ListStore > rulesStore
Gtk::TreeView rulesView
Gtk::CheckButton chk_enableYara
Gtk::CheckButton chk_enableSanesecurity
Gtk::Label lbl_scanPaths
Gtk::ListBox listbox_scanPaths
Gtk::Button btn_addScanPath
Gtk::Button btn_removeScanPath
Gtk::SpinButton spin_interval
SambaColumns sambaCols
Glib::RefPtr< Gtk::ListStore > sambaStore
Gtk::TreeView sambaView
Gtk::CheckButton chk_enableSamba
Gtk::Button btnAddSamba
Gtk::Button btnRemSamba
Gtk::Button btnScanNow
Gtk::Switch switchEnableSamba
bool enable_samba = false
std::vector< std::string > samba_dirs
Gtk::Switch antiphishSwitch
Gtk::Label antiphishStatus
Glib::RefPtr< Gtk::ListStore > phishStore
Gtk::TreeView phishView
Gtk::Switch googleSafeSwitch
Gtk::Entry googleSafeKeyEntry
Glib::RefPtr< Gtk::SingleSelection > whitelistSelection
Glib::RefPtr< Gtk::StringList > whitelistStore
Gtk::ListView whitelistView
PhishColumns phishCols
Gtk::ComboBoxText combo_language_
Gtk::Button btn_apply_language_
Gtk::CheckButton * chkSuspOnly = nullptr
Gtk::Entry * txtIgnPaths = nullptr
Gtk::Entry * txtCompany = nullptr
Gtk::Entry * txtIgnExt = nullptr
Gtk::Entry * txtSuspExt = nullptr
AllowlistCols allowCols
Glib::RefPtr< Gtk::ListStore > allowStore
Gtk::TreeView allowView
bool updatingToggle = false
std::map< std::string, bool > toggleControlled
BastionGuard::AliveFlag alive_ = BastionGuard::make_alive_flag()
Gtk::ScrolledWindow m_scroll
Gtk::Box m_content {Gtk::Orientation::VERTICAL, 16}
Gtk::Label m_title
Gtk::Label m_intro
Gtk::Frame m_serviceFrame
Gtk::Box m_serviceBox {Gtk::Orientation::VERTICAL, 12}
Gtk::Switch m_enableSwitch
Gtk::Label m_enableLabel
Gtk::Label m_statusLabel
Gtk::Label m_infoLabel
Gtk::Button m_applyButton
Gtk::Button m_refreshButton
Gtk::Frame m_detailsFrame
Gtk::Box m_detailsBox {Gtk::Orientation::VERTICAL, 8}
Gtk::Label m_savedPrefLabel
Gtk::Label m_serviceStateLabel
Gtk::Label m_autostartStateLabel
Gtk::Label m_backupStateLabel
Gtk::Label m_serviceTitle
Gtk::Label m_serviceBadge
Gtk::Label m_detailsTitle
Gtk::Label m_detailsBadge
bool m_updatingSwitch = false
sigc::signal< void(bool)> m_signalToggleProtectionRequested
std::string m_configPath
std::string m_backupPath
bool m_savedEnabled = true

Detailed Description

Definition at line 29 of file SettingsPage.hpp.

Constructor & Destructor Documentation

◆ SettingsPage() [1/2]

SettingsPage::SettingsPage ( ClamdConfig & config)
explicit

Definition at line 1450 of file SettingsPage.cpp.

1452: Gtk::Box(Gtk::Orientation::VERTICAL, 12),
1453 clamdConfig(config),
1455 quarantineLabel(_("Percorso quarantena: ") + Backend::getQuarantinePath()),
1456 quarantineButton(_("Seleziona cartella quarantena")),
1457 realtimeLabel(_("Antivirus real time: Disabilitato")),
1459 toggleAllLabel(_("Abilita tutte le opzioni")),
1461 antiransomStatus(_("Protezione disattivata"))
1462{
1463 sambaStore = Gtk::ListStore::create(sambaCols);
1464 sambaView.set_model(sambaStore);
1465 sambaView.append_column(_("Directory Samba"), sambaCols.col_path);
1466
1467 set_margin(12);
1468 stack.set_hexpand(true);
1469 stack.set_vexpand(true);
1470 stack.set_transition_type(Gtk::StackTransitionType::SLIDE_LEFT_RIGHT);
1471 stack.set_transition_duration(300);
1472
1473 stack_switcher.set_stack(stack);
1474 stack_switcher.set_hexpand(true);
1475 stack_switcher.set_halign(Gtk::Align::FILL);
1476
1477 append(stack_switcher);
1478 append(stack);
1479
1480 auto page_base = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
1481
1482 page_base->append(realtimeLabel);
1483 auto realtimeBox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 5);
1484 realtimeBox->set_hexpand(true);
1485 realtimeBox->set_halign(Gtk::Align::CENTER);
1486 realtimeBox->append(clamonaccSwitch);
1487 page_base->append(*realtimeBox);
1488
1489 bool clamonacc_enabled = isClamonaccRunning();
1490 clamonaccSwitch.set_active(clamonacc_enabled);
1491 realtimeLabel.set_text(clamonacc_enabled ?
1492 _("Antivirus real time: Abilitato") :
1493 _("Antivirus real time: Disabilitato"));
1494
1495 clamonaccSwitch.property_active().signal_changed().connect(
1496 sigc::mem_fun(*this, &SettingsPage::onRealtimeToggled)
1497 );
1498
1499 page_base->append(quarantineLabel);
1500 page_base->append(quarantineButton);
1501 quarantineButton.signal_clicked().connect(
1502 sigc::mem_fun(*this, &SettingsPage::onQuarantineClicked)
1503 );
1504
1505 auto framePaths = Gtk::make_managed<Gtk::Frame>(_("Cartelle monitorate (clamonacc)"));
1506 auto vboxPaths = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 5);
1507 vboxPaths->append(listbox_paths);
1508
1509 auto hboxButtons = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 5);
1510 hboxButtons->append(btn_addPath);
1511 hboxButtons->append(btn_removePath);
1512
1513 vboxPaths->append(*hboxButtons);
1514 framePaths->set_child(*vboxPaths);
1515 page_base->append(*framePaths);
1516
1517 for (auto& f : clamdConfig.getOnAccessPaths()) {
1518 auto row = Gtk::make_managed<Gtk::Label>(f);
1519 listbox_paths.append(*row);
1520 row->show();
1521 }
1522
1523 btn_addPath.signal_clicked().connect(sigc::mem_fun(*this, &SettingsPage::onAddPath));
1524 btn_removePath.signal_clicked().connect(sigc::mem_fun(*this, &SettingsPage::onRemovePath));
1525 btn_addPath.set_child(*Gtk::make_managed<Gtk::Label>(_("Aggiungi cartella")));
1526 btn_removePath.set_child(*Gtk::make_managed<Gtk::Label>(_("Rimuovi cartella")));
1527
1528
1529 page_order_.push_back(page_base);
1530 stack.add(*page_base, "base", _("Base"));
1531
1532
1533 auto page_adv = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
1534 auto frameScan = Gtk::make_managed<Gtk::Frame>(_("Opzioni di scansione"));
1535
1536 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
1537 scrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
1538 scrolled->set_expand(true);
1539
1540 auto flowScan = Gtk::make_managed<Gtk::FlowBox>();
1541 flowScan->set_valign(Gtk::Align::START);
1542 flowScan->set_max_children_per_line(4);
1543 flowScan->set_selection_mode(Gtk::SelectionMode::NONE);
1544
1545 auto scanOptions = clamdConfig.getScanOptions();
1546 for (auto& [opt, enabled] : scanOptions) {
1547 auto cb = Gtk::make_managed<Gtk::CheckButton>(opt);
1548 cb->set_active(enabled);
1549 checkOptions[opt] = cb;
1550 toggleControlled[opt] = false;
1551
1552 flowScan->append(*cb);
1553 cb->show();
1554
1555 cb->signal_toggled().connect([this, opt]() {
1556 if (updatingToggle) return;
1557 toggleControlled[opt] = false;
1558 });
1559 }
1560
1561 scrolled->set_child(*flowScan);
1562 frameScan->set_child(*scrolled);
1563
1564 auto lblWarning = Gtk::make_managed<Gtk::Label>(
1565 _("⚠️ Attenzione: modificare queste opzioni avanzate solo se si è sicuri.\n"
1566 "Un uso improprio può compromettere la protezione.")
1567 );
1568 lblWarning->set_wrap(true);
1569 lblWarning->set_margin_bottom(10);
1570 lblWarning->set_halign(Gtk::Align::FILL);
1571 lblWarning->set_justify(Gtk::Justification::CENTER);
1572
1573 lblWarning->get_style_context()->add_class("alert-warning");
1574
1575 page_adv->append(*lblWarning);
1576
1577 page_adv->append(*frameScan);
1578
1579 auto hboxToggleAll = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 5);
1580 hboxToggleAll->append(toggleAllLabel);
1581 hboxToggleAll->append(toggleAllSwitch);
1582 page_adv->append(*hboxToggleAll);
1583
1584 toggleAllSwitch.property_active().signal_changed().connect([this]() {
1585 if (updatingToggle) return;
1586 updatingToggle = true;
1587
1588 bool enabled = toggleAllSwitch.get_active();
1589 for (auto& [opt, cb] : checkOptions) {
1590 if (enabled && !cb->get_active()) {
1591 cb->set_active(true);
1592 toggleControlled[opt] = true;
1593 } else if (!enabled && toggleControlled[opt]) {
1594 cb->set_active(false);
1595 toggleControlled[opt] = false;
1596 }
1597 }
1598
1599 updatingToggle = false;
1600 toggleAllLabel.set_text(enabled ?
1601 _("Tutte le opzioni avanzate abilitate (toggle)") :
1602 _("Abilita tutte le opzioni avanzate"));
1603 });
1604
1605 page_adv->append(btn_save);
1606 btn_save.signal_clicked().connect(sigc::mem_fun(*this, &SettingsPage::onSave));
1607 btn_save.set_child(*Gtk::make_managed<Gtk::Label>(_("Salva configurazione")));
1608 auto frameCustomDB = Gtk::make_managed<Gtk::Frame>(_("Database firme personalizzato"));
1609
1610 auto boxCustomDB = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
1611 boxCustomDB->set_margin(10);
1612
1613
1614 page_order_.push_back(page_adv);
1615 stack.add(*page_adv, "advanced", _("Avanzate"));
1616
1617
1630
1631
1632}
#define _(s)
static std::string getQuarantinePath()
Definition Backend.cpp:496
std::vector< std::string > getOnAccessPaths() const
std::map< std::string, bool > getScanOptions() const
Gtk::ListBox listbox_paths
Gtk::Label antiransomStatus
void onQuarantineClicked()
Gtk::StackSwitcher stack_switcher
Gtk::Switch clamonaccSwitch
Gtk::Button btn_removePath
Gtk::Label toggleAllLabel
Gtk::Switch antiransomSwitch
Gtk::Button quarantineButton
void loadAdvancedConfig()
void build_clamav_db_tab()
Gtk::TreeView sambaView
void onRealtimeToggled()
void build_secure_payments_tab()
void build_system_services_tab()
Gtk::Button btn_addPath
std::map< std::string, bool > toggleControlled
void build_email_security_tab()
Gtk::Stack stack
Gtk::Button btn_save
Gtk::Label realtimeLabel
void build_antiransom_tab()
Gtk::Switch toggleAllSwitch
ClamdConfig & clamdConfig
void build_proxy_bypass_tab()
SambaColumns sambaCols
std::map< std::string, Gtk::CheckButton * > checkOptions
void build_antiphish_tab()
void build_whitelist_tab()
void build_options_tab()
std::vector< Gtk::Widget * > page_order_
void build_antiransom_advanced_tab()
void build_user_services_tab()
Glib::RefPtr< Gtk::ListStore > sambaStore
Gtk::Label quarantineLabel
bool isClamonaccRunning()
Gtk::TreeModelColumn< Glib::ustring > col_path

References _, antiransomStatus, antiransomSwitch, btn_addPath, btn_removePath, btn_save, build_antiphish_tab(), build_antiransom_advanced_tab(), build_antiransom_tab(), build_clamav_db_tab(), build_email_security_tab(), build_options_tab(), build_proxy_bypass_tab(), build_secure_payments_tab(), build_system_services_tab(), build_user_services_tab(), build_whitelist_tab(), checkOptions, clamdConfig, clamonaccSwitch, SettingsPage::SambaColumns::col_path, ClamdConfig::getOnAccessPaths(), ClamdConfig::getScanOptions(), isClamonaccRunning(), listbox_paths, loadAdvancedConfig(), onAddPath(), onQuarantineClicked(), onRealtimeToggled(), onRemovePath(), onSave(), page_order_, quarantineButton, quarantineLabel, realtimeLabel, sambaCols, sambaStore, sambaView, stack, stack_switcher, toggleAllLabel, toggleAllSwitch, toggleControlled, and updatingToggle.

◆ ~SettingsPage()

SettingsPage::~SettingsPage ( )
override

Definition at line 1443 of file SettingsPage.cpp.

1443 {
1444 // Invalida i lambda asincroni in volo: faranno early-return
1445 // invece di dereferenziare `this` dopo la distruzione.
1446 if (alive_) alive_->store(false, std::memory_order_release);
1447}
BastionGuard::AliveFlag alive_

References alive_.

◆ SettingsPage() [2/2]

SettingsPage::SettingsPage ( )

Definition at line 36 of file SettingsPage.cpp.

37: Gtk::Box(Gtk::Orientation::VERTICAL, 0),
38m_applyButton(_("Applica")),
39m_refreshButton(_("Aggiorna stato"))
40{
41 const auto cfgDir = Glib::get_user_config_dir() + "/bastionguard-sc";
42 m_configPath = cfgDir + "/service-control.ini";
44
45 buildUi();
48}
std::string m_configPath
Gtk::Button m_refreshButton
std::string m_backupPath
void loadPreference()
Gtk::Button m_applyButton
constexpr const char * kAutostartBackupPath

References _, buildUi(), loadPreference(), m_applyButton, m_backupPath, m_configPath, m_refreshButton, and refreshState().

Member Function Documentation

◆ autostartInstalled()

bool SettingsPage::autostartInstalled ( ) const
private

Definition at line 266 of file SettingsPage.cpp.

267{
268 return fs::exists(kAutostartPath) || fs::exists(kFallbackAutostartPath);
269}

Referenced by refreshState().

◆ backupExists()

bool SettingsPage::backupExists ( ) const
private

Definition at line 271 of file SettingsPage.cpp.

272{
273 return fs::exists(m_backupPath);
274}

References m_backupPath.

Referenced by refreshState().

◆ boolText()

std::string SettingsPage::boolText ( bool value)
staticprivate

Definition at line 277 of file SettingsPage.cpp.

278{
279 return value ? _("sì") : _("no");
280}

References _.

Referenced by refreshState().

◆ build_antiphish_tab()

void SettingsPage::build_antiphish_tab ( )
private

Definition at line 2097 of file SettingsPage.cpp.

2097 {
2098 auto page_phish = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
2099
2100 auto hbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
2101 auto lbl = Gtk::make_managed<Gtk::Label>(_("Protezione Anti-Phishing"));
2102 hbox->append(*lbl);
2103 hbox->append(antiphishSwitch);
2104 page_phish->append(*hbox);
2105
2106 bool running = isServiceActive("BastionGuard-phishing-scanner.service");
2107 antiphishSwitch.set_active(running);
2108 antiphishStatus.set_text(running
2109 ? _("Protezione Anti-Phishing: Attiva (servizio di sistema)")
2110 : _("Protezione Anti-Phishing: Disattivata (servizio non attivo)"));
2111 page_phish->append(antiphishStatus);
2112
2113 antiphishSwitch.property_active().signal_changed().connect(
2114 sigc::mem_fun(*this, &SettingsPage::onAntiphishToggled)
2115 );
2116 auto hbox_auto = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
2117 auto lbl_auto = Gtk::make_managed<Gtk::Label>(
2118 _("Aggiorna automaticamente la blacklist ogni 2 ore"));
2119 hbox_auto->append(*lbl_auto);
2120
2121 auto chk_auto_update = Gtk::make_managed<Gtk::CheckButton>();
2122 chk_auto_update->set_active(Backend::instance().isPhishAutoUpdateEnabled());
2123 chk_auto_update->set_halign(Gtk::Align::END);
2124 hbox_auto->append(*chk_auto_update);
2125
2126 chk_auto_update->signal_toggled().connect([this, chk_auto_update]() {
2127 bool enable = chk_auto_update->get_active();
2128 antiphishStatus.set_text(enable
2129 ? _("⏳ Attivazione aggiornamento automatico...")
2130 : _("⏳ Disattivazione aggiornamento automatico..."));
2131
2132 auto alive = alive_;
2133 std::thread([this, alive, enable]() {
2134 bool ok = Backend::instance().enablePhishAutoUpdate(enable);
2135 if (!alive->load()) return;
2136 Glib::signal_idle().connect_once([this, alive, enable, ok]() {
2137 BastionGuard::if_alive(alive, [this, enable, ok]() {
2138 if (ok) {
2139 antiphishStatus.set_text(enable
2140 ? _("✔ Aggiornamento automatico abilitato (ogni 2 ore)")
2141 : _("ℹ️ Aggiornamento automatico disabilitato"));
2142 } else {
2143 antiphishStatus.set_text(_("❌ Errore nella modifica del timer automatico"));
2144 }
2145 });
2146 });
2147 }).detach();
2148 });
2149
2150 page_phish->append(*hbox_auto);
2151 auto hbox_safe = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
2152 auto lbl_safe = Gtk::make_managed<Gtk::Label>(_("Usa Google Safe Browsing (verifica aggiuntiva)"));
2153 auto hbox_key = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
2154 auto lbl_key = Gtk::make_managed<Gtk::Label>(_("Chiave API Google Safe Browsing:"));
2155 lbl_key->set_halign(Gtk::Align::START);
2156
2157 googleSafeKeyEntry.set_placeholder_text(_("Inserisci la tua API key..."));
2158 googleSafeKeyEntry.set_hexpand(true);
2159 googleSafeKeyEntry.set_visibility(false);
2160 googleSafeKeyEntry.set_text(Backend::instance().getGoogleSafeApiKey());
2161 auto btn_save_key = Gtk::make_managed<Gtk::Button>(_("Salva"));
2162 btn_save_key->signal_clicked().connect([this]() {
2163 std::string key = googleSafeKeyEntry.get_text();
2166 antiphishStatus.set_text("✔ " + std::string(_("Chiave Google Safe salvata")));
2167 });
2168 auto btn_toggle_key = Gtk::make_managed<Gtk::Button>(_("Mostra"));
2169 btn_toggle_key->set_data("visible", new bool(false), [](void* p){ delete static_cast<bool*>(p); });
2170 btn_toggle_key->signal_clicked().connect(
2171 sigc::track_obj([this, btn_toggle_key]() {
2172 bool* visible = static_cast<bool*>(btn_toggle_key->get_data("visible"));
2173 *visible = !*visible;
2174
2175 googleSafeKeyEntry.set_visibility(*visible);
2176 btn_toggle_key->set_label(*visible ? _("Nascondi") : _("Mostra"));
2177 }, *btn_toggle_key)
2178 );
2179
2180 auto btn_test_key = Gtk::make_managed<Gtk::Button>(_("Verifica"));
2181 btn_test_key->signal_clicked().connect([this]() {
2182 antiphishStatus.set_text("⏳ " + std::string(_("Verifica chiave Google Safe...")));
2183 std::thread([this, alive = alive_]() {
2184 bool valid = Backend::instance().testGoogleSafeKey();
2185 if (!alive->load()) return;
2186 Glib::signal_idle().connect_once([this, alive, valid]() {
2187 BastionGuard::if_alive(alive, [this, valid]() {
2188 if (valid)
2189 antiphishStatus.set_text("✔ " + std::string(_("Chiave Google Safe valida")));
2190 else
2191 antiphishStatus.set_text("❌ " + std::string(_("Chiave Google Safe non valida")));
2192 });
2193 });
2194 }).detach();
2195 });
2196
2197
2198
2199 hbox_key->append(*lbl_key);
2200 hbox_key->append(googleSafeKeyEntry);
2201 hbox_key->append(*btn_toggle_key);
2202 hbox_key->append(*btn_save_key);
2203 hbox_key->append(*btn_test_key);
2204 page_phish->append(*hbox_key);
2205
2206 googleSafeSwitch.set_active(Backend::instance().isGoogleSafeEnabled());
2207
2208 hbox_safe->append(*lbl_safe);
2209 hbox_safe->append(googleSafeSwitch);
2210 page_phish->append(*hbox_safe);
2211
2212 googleSafeSwitch.property_active().signal_changed().connect([this]() {
2213 bool enabled = googleSafeSwitch.get_active();
2215
2216 antiphishStatus.set_text(enabled
2217 ? _("✔ Google Safe Browsing abilitato")
2218 : _("ℹ️ Google Safe Browsing disabilitato"));
2219 });
2220
2221 phishStore = Gtk::ListStore::create(phishCols);
2222 phishView.set_model(phishStore);
2223 phishView.append_column(_("Blacklist caricate"), phishCols.source);
2224
2225 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
2226 scrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
2227 scrolled->set_expand(true);
2228 scrolled->set_child(phishView);
2229 page_phish->append(*scrolled);
2231
2232 auto btn_update = Gtk::make_managed<Gtk::Button>(_("Aggiorna blacklist"));
2233 page_phish->append(*btn_update);
2234 btn_update->signal_clicked().connect([this]() {
2235 antiphishStatus.set_text("⏳ " + std::string(_("Aggiornamento blacklist...")));
2236
2237 std::thread([this, alive = alive_]() {
2238 bool ok = Backend::instance().updatePhishLists();
2239 if (!alive->load()) return;
2240
2241 Glib::signal_idle().connect_once([this, alive, ok]() {
2242 BastionGuard::if_alive(alive, [this, ok]() {
2243 if (ok) {
2244 antiphishStatus.set_text("✔ " + std::string(_("Blacklist aggiornata")));
2245
2247 if (isServiceActive("BastionGuard-phishing-scanner.service")) {
2248 antiphishStatus.set_text(_("♻ Riavvio servizio Anti-Phishing..."));
2249 int r1 = (bg_process::run({"pkexec", "/usr/libexec/bastionguard/bastionguard-service", "--system", "restart", "BastionGuard-phishing-scanner.service"}).exit_code);
2250 if (r1 == 0) {
2251 antiphishStatus.set_text(_("✔ Servizio Anti-Phishing riavviato con nuova blacklist"));
2252 } else {
2253 antiphishStatus.set_text(_("⚠ Errore durante il riavvio del servizio Anti-Phishing"));
2254 }
2255 }
2256
2257 } else {
2258 antiphishStatus.set_text("❌ " + std::string(_("Errore aggiornamento blacklist")));
2259 }
2260 });
2261 });
2262 }).detach();
2263});
2264
2265
2266 auto lblInfo = Gtk::make_managed<Gtk::Label>(
2267 "ℹ️ " + std::string(_("La lista completa aggiornata si trova in: phishing/blacklist.txt"))
2268 );
2269 lblInfo->set_wrap(true);
2270 page_phish->append(*lblInfo);
2271 auto frameFirewall = Gtk::make_managed<Gtk::Frame>();
2272 frameFirewall->set_hexpand(true);
2273
2274 auto boxFirewall = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
2275 boxFirewall->set_margin(12);
2276 boxFirewall->set_hexpand(true);
2277 auto lblFwTitle = Gtk::make_managed<Gtk::Label>(
2278 _("Blocco IP automatico (Firewall)")
2279 );
2280 lblFwTitle->set_halign(Gtk::Align::START);
2281 lblFwTitle->add_css_class("card-title");
2282 auto lblFwToggle = Gtk::make_managed<Gtk::Label>(
2283 _("Abilita blocco IP automatico")
2284 );
2285 lblFwToggle->set_halign(Gtk::Align::START);
2286
2287 auto swFirewall = Gtk::make_managed<Gtk::Switch>();
2288 swFirewall->set_active(Backend::instance().isFirewallEnabled());
2289
2290 auto hboxFwToggle = Gtk::make_managed<Gtk::CenterBox>();
2291 hboxFwToggle->set_start_widget(*lblFwToggle);
2292 hboxFwToggle->set_end_widget(*swFirewall);
2293 auto lblFwDesc = Gtk::make_managed<Gtk::Label>(
2294 _("Blocca automaticamente gli IP malevoli rilevati dal modulo Anti-Phishing\n"
2295 "utilizzando il firewall di sistema (UFW / firewalld).")
2296 );
2297 lblFwDesc->set_wrap(true);
2298 lblFwDesc->set_halign(Gtk::Align::START);
2299 lblFwDesc->add_css_class("card-description");
2300 auto lblFwStatus = Gtk::make_managed<Gtk::Label>();
2301 lblFwStatus->set_halign(Gtk::Align::START);
2302 auto updateFwStatus = [lblFwStatus]() {
2303 auto& backend = Backend::instance();
2304
2305 if (!backend.isFirewallEnabled()) {
2306 lblFwStatus->set_text(_("Firewall IP: Disattivato"));
2307 lblFwStatus->remove_css_class("status-ok");
2308 lblFwStatus->add_css_class("status-muted");
2309 return;
2310 }
2311
2312 switch (backend.getFirewallType()) {
2313 case FirewallType::UFW:
2314 lblFwStatus->set_text(_("Firewall IP attivo: UFW"));
2315 break;
2317 lblFwStatus->set_text(_("Firewall IP attivo: firewalld"));
2318 break;
2319 default:
2320 lblFwStatus->set_text(_("Firewall IP attivo"));
2321 break;
2322 }
2323
2324 lblFwStatus->remove_css_class("status-muted");
2325 lblFwStatus->add_css_class("status-ok");
2326 };
2327
2328 updateFwStatus();
2329
2330 auto btnFirewall = Gtk::make_managed<Gtk::Button>(
2331 _("Configura blocco IP firewall")
2332 );
2333 btnFirewall->set_halign(Gtk::Align::END);
2334 btnFirewall->add_css_class("suggested-action");
2335
2336 btnFirewall->signal_clicked().connect(
2337 [this, updateFwStatus]() {
2338
2339 auto dialog = std::make_unique<FirewallChoiceDialog>();
2340
2341 if (auto *win = dynamic_cast<Gtk::Window*>(get_root()))
2342 dialog->set_transient_for(*win);
2343
2344 dialog->set_modal(true);
2345
2346 dialog->signal_firewall_selected.connect(
2347 [updateFwStatus](FirewallType type) {
2348
2349 auto& backend = Backend::instance();
2350
2351 backend.setFirewallType(type);
2352 backend.setFirewallEnabled(true);
2353
2354 backend.applyFirewallFromPhishingBlacklist();
2355
2356 updateFwStatus();
2357 }
2358 );
2359
2360 dialog->present();
2361 dialog.release();
2362 });
2363
2364 swFirewall->property_active().signal_changed().connect(
2365 [this, swFirewall, updateFwStatus]() {
2366 bool enabled = swFirewall->get_active();
2368
2369 antiphishStatus.set_text(
2370 enabled
2371 ? _("✔ Blocco IP firewall abilitato")
2372 : _("ℹ️ Blocco IP firewall disabilitato")
2373 );
2374
2375 updateFwStatus();
2376 }
2377 );
2378
2379 boxFirewall->append(*lblFwTitle);
2380 boxFirewall->append(*hboxFwToggle);
2381 boxFirewall->append(*lblFwDesc);
2382 boxFirewall->append(*lblFwStatus);
2383 boxFirewall->append(*btnFirewall);
2384
2385 frameFirewall->set_child(*boxFirewall);
2386 page_phish->append(*frameFirewall);
2387
2388
2389 page_order_.push_back(page_phish);
2390 stack.add(*page_phish, "anti-phishing", _("Anti-Phishing"));
2391}
FirewallType
void setGoogleSafeEnabled(bool enabled)
Definition Backend.hpp:86
bool testGoogleSafeKey()
Definition Backend.cpp:1680
bool updatePhishLists()
Definition Backend.cpp:1086
bool enablePhishAutoUpdate(bool enable)
Definition Backend.cpp:1732
void setFirewallEnabled(bool enabled)
Definition Backend.cpp:3126
static Backend & instance()
Definition Backend.cpp:830
void setGoogleSafeApiKey(const std::string &key)
Definition Backend.hpp:87
void saveGoogleSafeConfig()
Definition Backend.cpp:1648
Gtk::TreeModelColumn< Glib::ustring > source
Gtk::Switch antiphishSwitch
Gtk::Switch googleSafeSwitch
Gtk::TreeView phishView
void onAntiphishToggled()
Gtk::Entry googleSafeKeyEntry
void refreshPhishLists()
Gtk::Label antiphishStatus
PhishColumns phishCols
Glib::RefPtr< Gtk::ListStore > phishStore
void if_alive(const AliveFlag &alive, Fn &&fn)
bool isServiceActive(const std::string &service, bool user=false)
Result run(const std::vector< std::string > &args, bool merge_stderr=false, std::size_t limit=8U *1024U *1024U, const std::map< std::string, std::string > &environment={}, const std::function< bool(const std::string &)> &on_line={})

References _, alive_, antiphishStatus, antiphishSwitch, Backend::enablePhishAutoUpdate(), FIREWALLD, googleSafeKeyEntry, googleSafeSwitch, BastionGuard::if_alive(), Backend::instance(), loadPhishLists(), onAntiphishToggled(), page_order_, phishCols, phishStore, phishView, refreshPhishLists(), bg_process::run(), Backend::saveGoogleSafeConfig(), Backend::setFirewallEnabled(), Backend::setGoogleSafeApiKey(), Backend::setGoogleSafeEnabled(), SettingsPage::PhishColumns::source, stack, Backend::testGoogleSafeKey(), UFW, and Backend::updatePhishLists().

Referenced by SettingsPage().

◆ build_antiransom_advanced_tab()

void SettingsPage::build_antiransom_advanced_tab ( )
private

Definition at line 3296 of file SettingsPage.cpp.

3296 {
3297 auto page_adv = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
3298 page_adv->set_margin(12);
3299
3300 // ===== Allowlist SHA256 =====
3301 auto frameAllow = Gtk::make_managed<Gtk::Frame>(_("Allowlist SHA256 Anti-ransomware"));
3302 auto vboxAllow = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 6);
3303 vboxAllow->set_margin(6);
3304
3305 allowStore = Gtk::ListStore::create(allowCols);
3306 allowView.set_model(allowStore);
3307 allowView.append_column(_("SHA256"), allowCols.col_hash);
3308 allowView.append_column(_("Regola (opzionale)"), allowCols.col_rule);
3309
3310 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
3311 scrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
3312 scrolled->set_expand(true);
3313 scrolled->set_child(allowView);
3314 vboxAllow->append(*scrolled);
3315
3316 auto btnAdd = Gtk::make_managed<Gtk::Button>(_("Aggiungi"));
3317 auto btnDel = Gtk::make_managed<Gtk::Button>(_("Rimuovi"));
3318 auto btnBox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
3319 btnBox->append(*btnAdd);
3320 btnBox->append(*btnDel);
3321 vboxAllow->append(*btnBox);
3322 frameAllow->set_child(*vboxAllow);
3323 page_adv->append(*frameAllow);
3324
3326
3327 btnAdd->signal_clicked().connect([this]() {
3328 auto dialog = std::make_shared<Gtk::Dialog>();
3329 dialog->set_title(_("Aggiungi SHA256"));
3330 dialog->set_modal(true);
3331 dialog->set_default_size(360, 180);
3332 dialog->add_css_class("sha-dialog");
3333
3334 auto shaEntry = Gtk::make_managed<Gtk::Entry>();
3335 auto ruleEntry = Gtk::make_managed<Gtk::Entry>();
3336 shaEntry->set_placeholder_text("SHA256...");
3337 ruleEntry->set_placeholder_text("Regola (facoltativa)");
3338
3339 shaEntry->set_margin_bottom(6);
3340 ruleEntry->set_margin_bottom(6);
3341
3342 auto content = dialog->get_content_area();
3343 content->set_margin(12);
3344 content->set_spacing(8);
3345 content->append(*shaEntry);
3346 content->append(*ruleEntry);
3347
3348 dialog->add_button(_("_Annulla"), Gtk::ResponseType::CANCEL);
3349 dialog->add_button(_("_Aggiungi"), Gtk::ResponseType::OK);
3350
3351 dialog->signal_show().connect([shaEntry]() {
3352 shaEntry->grab_focus();
3353 });
3354
3355 dialog->signal_response().connect([this, dialog, shaEntry, ruleEntry](int response) {
3356 if (response == Gtk::ResponseType::OK) {
3357 auto sha = shaEntry->get_text();
3358 sha.erase(0, sha.find_first_not_of(" \t\n\r"));
3359 sha.erase(sha.find_last_not_of(" \t\n\r") + 1);
3360
3361 if (!sha.empty()) {
3362 auto row = *(allowStore->append());
3363 row[allowCols.col_hash] = sha;
3364 row[allowCols.col_rule] = ruleEntry->get_text();
3365 }
3366 }
3367 dialog->close();
3368 });
3369
3370 dialog->set_visible(true);
3371 });
3372
3373 btnDel->signal_clicked().connect([this]() {
3374 if (auto sel = allowView.get_selection()) {
3375 if (auto iter = sel->get_selected())
3376 allowStore->erase(iter);
3377 }
3378 });
3379
3380 auto frameFilters = Gtk::make_managed<Gtk::Frame>(_("Filtri Anti-Falsi Positivi"));
3381 auto grid = Gtk::make_managed<Gtk::Grid>();
3382 grid->set_row_spacing(6);
3383 grid->set_column_spacing(6);
3384 grid->set_margin(6);
3385
3386 chkSuspOnly = Gtk::make_managed<Gtk::CheckButton>(_("Analizza solo file sospetti"));
3387 auto lblIgnPaths = Gtk::make_managed<Gtk::Label>(_("Percorsi da ignorare"));
3388 txtIgnPaths = Gtk::make_managed<Gtk::Entry>();
3389 txtIgnPaths->set_placeholder_text("/home/*/.cache;/var/cache;/tmp;...");
3390 txtIgnPaths->add_css_class("home-entry");
3391
3392 auto lblCompany = Gtk::make_managed<Gtk::Label>(_("Percorsi aziendali sicuri"));
3393 txtCompany = Gtk::make_managed<Gtk::Entry>();
3394 txtCompany->set_placeholder_text("/srv/company;/mnt/share;/opt/apps;...");
3395 txtCompany->add_css_class("company-entry");
3396
3397 auto lblIgnExt = Gtk::make_managed<Gtk::Label>(_("Estensioni da ignorare"));
3398 txtIgnExt = Gtk::make_managed<Gtk::Entry>();
3399 txtIgnExt->set_placeholder_text(".jpg;.png;.pdf;...");
3400 txtIgnExt->add_css_class("whitelist-entry");
3401
3402 auto lblSuspExt = Gtk::make_managed<Gtk::Label>(_("Estensioni sospette"));
3403 txtSuspExt = Gtk::make_managed<Gtk::Entry>();
3404 txtSuspExt->set_placeholder_text(".exe;.dll;.js;.sh;...");
3405 txtSuspExt->add_css_class("danger-entry");
3406
3407 grid->attach(*chkSuspOnly, 0, 0, 2, 1);
3408 grid->attach(*lblIgnPaths, 0, 1, 1, 1);
3409 grid->attach(*txtIgnPaths, 1, 1, 1, 1);
3410 grid->attach(*lblCompany, 0, 2, 1, 1);
3411 grid->attach(*txtCompany, 1, 2, 1, 1);
3412 grid->attach(*lblIgnExt, 0, 3, 1, 1);
3413 grid->attach(*txtIgnExt, 1, 3, 1, 1);
3414 grid->attach(*lblSuspExt, 0, 4, 1, 1);
3415 grid->attach(*txtSuspExt, 1, 4, 1, 1);
3416
3417 frameFilters->set_child(*grid);
3418 page_adv->append(*frameFilters);
3419
3420 // === Pulsante Salva impostazioni ===
3421 auto btnSave = Gtk::make_managed<Gtk::Button>(_("Salva impostazioni avanzate"));
3422 page_adv->append(*btnSave);
3423
3424 btnSave->signal_clicked().connect([this]() {
3427 chkSuspOnly->get_active(),
3428 txtIgnPaths->get_text(),
3429 txtIgnExt->get_text(),
3430 txtSuspExt->get_text()
3431 );
3432
3433
3434 antiransomStatus.set_text(_("✔ Impostazioni avanzate salvate"));
3435 });
3436
3438 page_order_.push_back(page_adv);
3439 stack.add(*page_adv, "advanced-anti-ransomware", _("Anti-Ransomware avanzate"));
3440}
Glib::RefPtr< Gtk::ListStore > allowStore
Gtk::Entry * txtSuspExt
void saveAdvancedConfig(bool suspicious_only, const Glib::ustring &ignore_paths, const Glib::ustring &ignore_ext, const Glib::ustring &suspicious_ext)
AllowlistCols allowCols
Gtk::Entry * txtCompany
Gtk::Entry * txtIgnExt
Gtk::TreeView allowView
Gtk::Entry * txtIgnPaths
Gtk::CheckButton * chkSuspOnly
Gtk::TreeModelColumn< Glib::ustring > col_hash
Gtk::TreeModelColumn< Glib::ustring > col_rule

References _, allowCols, allowStore, allowView, antiransomStatus, chkSuspOnly, SettingsPage::AllowlistCols::col_hash, SettingsPage::AllowlistCols::col_rule, loadAdvancedConfig(), loadAllowlistUI(), page_order_, saveAdvancedConfig(), saveAllowlistUI(), stack, txtCompany, txtIgnExt, txtIgnPaths, and txtSuspExt.

Referenced by SettingsPage().

◆ build_antiransom_tab()

void SettingsPage::build_antiransom_tab ( )
private

Definition at line 1719 of file SettingsPage.cpp.

1719 {
1720 auto page_ransom = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
1721
1722 auto hboxRan = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
1723 auto lblRan = Gtk::make_managed<Gtk::Label>(_("Protezione Anti-Ransomware"));
1724 hboxRan->append(*lblRan);
1725 hboxRan->append(antiransomSwitch);
1726 page_ransom->append(*hboxRan);
1727
1728 bool running = isServiceActive("BastionGuard-ransomware-scanner.service", true);
1729 antiransomSwitch.set_active(running);
1730 antiransomStatus.set_text(running
1731 ? _("Protezione Anti-Ransomware: Attiva")
1732 : _("Protezione Anti-Ransomware: Disattivata (servizio non attivo)"));
1733 page_ransom->append(antiransomStatus);
1734
1735 antiransomSwitch.property_active().signal_changed().connect(
1736 sigc::mem_fun(*this, &SettingsPage::onAntiransomToggled)
1737 );
1738
1739 rulesStore = Gtk::ListStore::create(ruleCols);
1740 rulesView.set_model(rulesStore);
1741 rulesView.append_column(_("Regole YARA in uso"), ruleCols.name);
1742
1743 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
1744 scrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
1745 scrolled->set_expand(true);
1746 scrolled->set_child(rulesView);
1747 scrolled->set_min_content_height(100);
1748 page_ransom->append(*scrolled);
1749
1750 loadYaraRules();
1751
1752 auto btn_updateYara = Gtk::make_managed<Gtk::Button>(_("Aggiorna regole YARA"));
1753 page_ransom->append(*btn_updateYara);
1754
1755 btn_updateYara->signal_clicked().connect([this]() {
1756 antiransomStatus.set_text(_("⏳ Aggiornamento regole YARA in corso..."));
1757
1758 auto alive = alive_;
1759 std::thread([this, alive]() {
1760 bool ok = Backend::instance().updateYaraRules();
1761 if (!alive->load()) return;
1762
1763 Glib::signal_idle().connect_once([this, alive, ok]() {
1764 BastionGuard::if_alive(alive, [this, ok]() {
1765 if (ok) {
1766 antiransomStatus.set_text(_("✔ Regole YARA aggiornate con successo"));
1768 } else {
1769 antiransomStatus.set_text(_("❌ Errore durante l'aggiornamento delle regole YARA"));
1770 }
1771 });
1772 });
1773 }).detach();
1774 });
1775
1776
1777 auto btn_updateSanesec = Gtk::make_managed<Gtk::Button>(_("Aggiorna Sanesecurity DB"));
1778 page_ransom->append(*btn_updateSanesec);
1779
1780 btn_updateSanesec->signal_clicked().connect([this]() {
1781 antiransomStatus.set_text(_("⏳ Aggiornamento Sanesecurity DB in corso..."));
1782
1783 auto alive = alive_;
1784 std::thread([this, alive]() {
1786 if (!alive->load()) return;
1787
1788 Glib::signal_idle().connect_once([this, alive, ok]() {
1789 BastionGuard::if_alive(alive, [this, ok]() {
1790 if (ok) {
1791 antiransomStatus.set_text(_("✔ Sanesecurity DB aggiornato con successo"));
1792 } else {
1793 antiransomStatus.set_text(_("❌ Errore durante l'aggiornamento del Sanesecurity DB"));
1794 }
1795 });
1796 });
1797 }).detach();
1798 });
1799
1800
1801 bool use_rules, use_db;
1802 int interval;
1803 std::vector<std::string> scan_dirs;
1804 loadScannerConfig(use_rules, use_db, interval, scan_dirs);
1805
1806 auto chk_rules = Gtk::make_managed<Gtk::CheckButton>(_("Usa regole YARA"));
1807 chk_rules->set_active(use_rules);
1808 page_ransom->append(*chk_rules);
1809
1810 auto chk_db = Gtk::make_managed<Gtk::CheckButton>(_("Usa DB Sanesecurity"));
1811 chk_db->set_active(use_db);
1812 page_ransom->append(*chk_db);
1813
1814 auto lblDirs = Gtk::make_managed<Gtk::Label>(_("Cartelle da scansionare:"));
1815 page_ransom->append(*lblDirs);
1816
1817 auto list_dirs = Gtk::make_managed<Gtk::ListBox>();
1818 for (auto& d : scan_dirs) {
1819 auto row = Gtk::make_managed<Gtk::Label>(d);
1820 row->set_visible(true);
1821 list_dirs->append(*row);
1822 }
1823 page_ransom->append(*list_dirs);
1824
1825 auto btn_addDir = Gtk::make_managed<Gtk::Button>(_("Aggiungi cartella"));
1826 auto btn_rmDir = Gtk::make_managed<Gtk::Button>(_("Rimuovi cartella"));
1827 auto hboxDirs = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 5);
1828 hboxDirs->append(*btn_addDir);
1829 hboxDirs->append(*btn_rmDir);
1830 page_ransom->append(*hboxDirs);
1831
1832 btn_addDir->signal_clicked().connect([list_dirs]() {
1833 auto dialog = new Gtk::FileChooserDialog(_("Seleziona cartella da scansionare"),
1834 Gtk::FileChooser::Action::SELECT_FOLDER);
1835 dialog->add_button(_("_Annulla"), Gtk::ResponseType::CANCEL);
1836 dialog->add_button(_("_Seleziona"), Gtk::ResponseType::OK);
1837 dialog->signal_response().connect([dialog, list_dirs](int response) {
1838 if (response == Gtk::ResponseType::OK) {
1839 auto folder = dialog->get_file()->get_path();
1840 auto row = Gtk::make_managed<Gtk::Label>(folder);
1841 row->set_visible(true);
1842 list_dirs->append(*row);
1843 }
1844 dialog->hide();
1845 delete dialog;
1846 });
1847 dialog->show();
1848 });
1849
1850 btn_rmDir->signal_clicked().connect([list_dirs]() {
1851 if (auto row = list_dirs->get_selected_row()) {
1852 list_dirs->remove(*row);
1853 }
1854 });
1855
1856 auto spin_interval = Gtk::make_managed<Gtk::SpinButton>();
1857 spin_interval->set_range(1, 120);
1858 spin_interval->set_value(interval);
1859 spin_interval->set_increments(1, 5);
1860 auto hboxInt = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 5);
1861 hboxInt->append(*Gtk::make_managed<Gtk::Label>(_("Intervallo scansione (min):")));
1862 hboxInt->append(*spin_interval);
1863 page_ransom->append(*hboxInt);
1864
1865 auto btn_saveConf = Gtk::make_managed<Gtk::Button>(_("Salva configurazione scanner"));
1866 page_ransom->append(*btn_saveConf);
1867 btn_saveConf->signal_clicked().connect([this, chk_rules, chk_db, spin_interval, list_dirs]() {
1868 std::vector<std::string> dirs;
1869 // Recupera le directory di scansione principali
1870 for (auto row : list_dirs->get_children()) {
1871 if (auto lbl = dynamic_cast<Gtk::Label*>(row))
1872 dirs.push_back(lbl->get_text());
1873 }
1874
1876 chk_rules->get_active(),
1877 chk_db->get_active(),
1878 spin_interval->get_value_as_int(),
1879 dirs
1880 );
1881
1882 });
1883
1884 page_order_.push_back(page_ransom);
1885 stack.add(*page_ransom, "anti-ransomware", _("Anti-Ransomware"));
1886}
bool updateYaraRules(std::function< void(int, int, const std::string &)> progressCallback=nullptr)
Definition Backend.cpp:857
bool updateSanesecurityDB(std::function< void(int, int, const std::string &)> progressCallback=nullptr)
Definition Backend.cpp:1542
Gtk::TreeModelColumn< Glib::ustring > name
void saveScannerConfig(bool use_rules, bool use_db, int interval, const std::vector< std::string > &dirs)
void refreshAntiransomRules()
RuleColumns ruleCols
Gtk::TreeView rulesView
void loadScannerConfig(bool &use_rules, bool &use_db, int &interval, std::vector< std::string > &dirs)
void onAntiransomToggled()
Gtk::SpinButton spin_interval
Glib::RefPtr< Gtk::ListStore > rulesStore

References _, alive_, antiransomStatus, antiransomSwitch, BastionGuard::if_alive(), Backend::instance(), loadScannerConfig(), loadYaraRules(), SettingsPage::RuleColumns::name, onAntiransomToggled(), page_order_, refreshAntiransomRules(), ruleCols, rulesStore, rulesView, saveScannerConfig(), spin_interval, stack, Backend::updateSanesecurityDB(), and Backend::updateYaraRules().

Referenced by SettingsPage().

◆ build_clamav_db_tab()

void SettingsPage::build_clamav_db_tab ( )
private

Definition at line 4763 of file SettingsPage.cpp.

4764{
4765 auto page_db = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
4766 page_db->set_margin(12);
4767
4768 auto frame = Gtk::make_managed<Gtk::Frame>(_("Database firme ClamAV"));
4769 auto inner = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
4770 inner->set_margin(10);
4771
4772 auto lblInfo = Gtk::make_managed<Gtk::Label>(
4773 _("Questa sezione mostra le firme presenti nel database ClamAV.\n"
4774 "Le firme personalizzate installate in /var/lib/clamav verranno caricate automaticamente da clamd.")
4775 );
4776 lblInfo->set_wrap(true);
4777 lblInfo->set_halign(Gtk::Align::FILL);
4778 lblInfo->add_css_class("alert-info");
4779 inner->append(*lblInfo);
4780
4781 auto lblPathTitle = Gtk::make_managed<Gtk::Label>(_("Percorso database:"));
4782 lblPathTitle->set_halign(Gtk::Align::START);
4783 inner->append(*lblPathTitle);
4784
4785 auto lblPath = Gtk::make_managed<Gtk::Label>("/var/lib/clamav");
4786 lblPath->set_xalign(0.0);
4787 lblPath->add_css_class("readonly-path");
4788 inner->append(*lblPath);
4789
4790 auto rowTop = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
4791
4792 auto lblCount = Gtk::make_managed<Gtk::Label>();
4793 lblCount->set_halign(Gtk::Align::START);
4794 lblCount->add_css_class("status-muted");
4795 clamdb_count_label_ = lblCount;
4796
4797 auto btnRefresh = Gtk::make_managed<Gtk::Button>(_("Aggiorna"));
4798 btnRefresh->set_halign(Gtk::Align::END);
4799 btnRefresh->add_css_class("suggested-action");
4800
4801 rowTop->append(*lblCount);
4802 rowTop->append(*btnRefresh);
4803 inner->append(*rowTop);
4804
4805 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
4806 scrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
4807 scrolled->set_expand(true);
4808 scrolled->set_min_content_height(220);
4809
4810 auto listBox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 6);
4811 listBox->set_margin_start(6);
4812 scrolled->set_child(*listBox);
4813
4814
4815 inner->append(*scrolled);
4816
4817 refresh_clamav_db_list(listBox);
4818 btnRefresh->signal_clicked().connect([this, listBox]() {
4819 refresh_clamav_db_list(listBox);
4820 });
4821
4822 frame->set_child(*inner);
4823 page_db->append(*frame);
4824
4825 page_order_.push_back(page_db);
4826 stack.add(*page_db, "clamav-db", _("DB ClamAV"));
4827}
void refresh_clamav_db_list(Gtk::Box *listBox)
Gtk::Label * clamdb_count_label_

References _, clamdb_count_label_, page_order_, refresh_clamav_db_list(), and stack.

Referenced by SettingsPage().

◆ build_email_security_tab()

void SettingsPage::build_email_security_tab ( )
private

Definition at line 4829 of file SettingsPage.cpp.

4829 {
4830 auto cfg = load_mail_security_config();
4831
4832 auto page = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 0);
4833 page->set_hexpand(true);
4834 page->set_vexpand(true);
4835
4836 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
4837 scrolled->set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC);
4838 scrolled->set_hexpand(true);
4839 scrolled->set_vexpand(true);
4840
4841 auto outer = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 0);
4842 outer->set_margin_top(28);
4843 outer->set_margin_bottom(28);
4844 outer->set_margin_start(24);
4845 outer->set_margin_end(24);
4846 outer->set_hexpand(true);
4847 outer->set_vexpand(true);
4848
4849 auto center = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
4850 center->set_halign(Gtk::Align::CENTER);
4851 center->set_valign(Gtk::Align::START);
4852 center->set_hexpand(true);
4853 center->set_size_request(820, -1);
4854
4855 auto frame = Gtk::make_managed<Gtk::Frame>();
4856 frame->set_hexpand(true);
4857
4858 auto inner = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
4859 inner->set_margin_top(20);
4860 inner->set_margin_bottom(20);
4861 inner->set_margin_start(20);
4862 inner->set_margin_end(20);
4863
4864 auto title = Gtk::make_managed<Gtk::Label>(_("Protezione Email"));
4865 title->set_halign(Gtk::Align::START);
4866 title->set_xalign(0.0f);
4867 title->add_css_class("card-title");
4868 inner->append(*title);
4869
4870 auto tabs_switcher = Gtk::make_managed<Gtk::StackSwitcher>();
4871 auto tabs = Gtk::make_managed<Gtk::Stack>();
4872 tabs->set_hexpand(true);
4873 tabs->set_vexpand(true);
4874 tabs->set_transition_type(Gtk::StackTransitionType::SLIDE_LEFT_RIGHT);
4875 tabs->set_transition_duration(250);
4876 tabs_switcher->set_stack(*tabs);
4877 tabs_switcher->set_halign(Gtk::Align::FILL);
4878 tabs_switcher->set_hexpand(true);
4879
4880 auto profiles = std::make_shared<std::vector<MailRelayProfile>>(cfg.profiles);
4881 auto selected_profile = std::make_shared<int>(0);
4882 auto ui_updating = std::make_shared<bool>(false);
4883
4884 if (profiles->empty()) {
4885 MailRelayProfile p;
4886 p.id = "";
4887 p.label = "";
4888 p.signature.logo_path = "/usr/share/BastionGuard/data/logo.png";
4889 profiles->push_back(p);
4890 }
4891
4892 auto mkLabel = [](const Glib::ustring& text) {
4893 auto lbl = Gtk::make_managed<Gtk::Label>(text);
4894 lbl->set_halign(Gtk::Align::START);
4895 lbl->set_xalign(0.0f);
4896 return lbl;
4897 };
4898
4899 auto make_switch_row = [](const Glib::ustring& txt, Gtk::Switch& sw) {
4900 auto row = Gtk::make_managed<Gtk::CenterBox>();
4901 auto lbl = Gtk::make_managed<Gtk::Label>(txt);
4902 lbl->set_halign(Gtk::Align::START);
4903 lbl->set_xalign(0.0f);
4904 row->set_start_widget(*lbl);
4905 row->set_end_widget(sw);
4906 return row;
4907 };
4908
4909 auto tab_general = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
4910 tab_general->set_margin_top(12);
4911 tab_general->set_margin_bottom(12);
4912 tab_general->set_margin_start(12);
4913 tab_general->set_margin_end(12);
4914
4915 auto swEnable = Gtk::make_managed<Gtk::Switch>();
4916 swEnable->set_active(cfg.enabled);
4917
4918 auto swScan = Gtk::make_managed<Gtk::Switch>();
4919 swScan->set_active(cfg.scan_outgoing);
4920
4921 auto swSig = Gtk::make_managed<Gtk::Switch>();
4922 swSig->set_active(cfg.inject_signature);
4923
4924 auto swAdvertiseStartTls = Gtk::make_managed<Gtk::Switch>();
4925 swAdvertiseStartTls->set_active(cfg.advertise_starttls);
4926
4927 auto swImplicitTlsListener = Gtk::make_managed<Gtk::Switch>();
4928 swImplicitTlsListener->set_active(cfg.enable_implicit_tls_listener);
4929
4930 tab_general->append(*make_switch_row(_("Abilita protezione email"), *swEnable));
4931 tab_general->append(*make_switch_row(_("Scansiona email in uscita"), *swScan));
4932 tab_general->append(*make_switch_row(_("Inserisci firma automatica"), *swSig));
4933 tab_general->append(*make_switch_row(_("Pubblica STARTTLS"), *swAdvertiseStartTls));
4934 tab_general->append(*make_switch_row(_("Abilita listener TLS implicito"), *swImplicitTlsListener));
4935
4936
4937 auto tab_signature = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
4938 tab_signature->set_margin_top(12);
4939 tab_signature->set_margin_bottom(12);
4940 tab_signature->set_margin_start(12);
4941 tab_signature->set_margin_end(12);
4942
4943 auto sName = Gtk::make_managed<Gtk::Entry>();
4944 auto sRole = Gtk::make_managed<Gtk::Entry>();
4945 auto sCompany = Gtk::make_managed<Gtk::Entry>();
4946 auto sPhone = Gtk::make_managed<Gtk::Entry>();
4947 auto sWeb = Gtk::make_managed<Gtk::Entry>();
4948
4949 auto sig_grid = Gtk::make_managed<Gtk::Grid>();
4950 sig_grid->set_row_spacing(10);
4951 sig_grid->set_column_spacing(12);
4952
4953 int sr = 0;
4954 auto attach_sig_row = [&](const Glib::ustring& lbl, Gtk::Widget& w) {
4955 sig_grid->attach(*mkLabel(lbl), 0, sr, 1, 1);
4956 sig_grid->attach(w, 1, sr, 1, 1);
4957 sr++;
4958 };
4959
4960 attach_sig_row(_("Nome visualizzato"), *sName);
4961 attach_sig_row(_("Ruolo"), *sRole);
4962 attach_sig_row(_("Azienda"), *sCompany);
4963 attach_sig_row(_("Telefono"), *sPhone);
4964 attach_sig_row(_("Sito web"), *sWeb);
4965
4966 auto fixedLogoInfo = Gtk::make_managed<Gtk::Label>(
4967 _("Logo fisso utilizzato: /usr/share/BastionGuard/data/logo.png")
4968 );
4969 fixedLogoInfo->set_halign(Gtk::Align::START);
4970 fixedLogoInfo->set_xalign(0.0f);
4971
4972 tab_signature->append(*sig_grid);
4973 tab_signature->append(*fixedLogoInfo);
4974
4975 auto load_signature_fields = [=]() {
4976 if (profiles->empty()) return;
4977 *ui_updating = true;
4978
4979 auto& s = (*profiles)[*selected_profile].signature;
4980 sName->set_text(s.display_name);
4981 sRole->set_text(s.job_title);
4982 sCompany->set_text(s.company);
4983 sPhone->set_text(s.phone);
4984 sWeb->set_text(s.website);
4985
4986 *ui_updating = false;
4987 };
4988
4989 auto save_signature_fields = [=]() {
4990 if (profiles->empty()) return;
4991 auto& s = (*profiles)[*selected_profile].signature;
4992 s.display_name = sName->get_text();
4993 s.job_title = sRole->get_text();
4994 s.company = sCompany->get_text();
4995 s.phone = sPhone->get_text();
4996 s.website = sWeb->get_text();
4997 s.logo_path = "/usr/share/BastionGuard/data/logo.png";
4998 };
4999
5000 auto tab_thunderbird = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
5001 tab_thunderbird->set_margin_top(12);
5002 tab_thunderbird->set_margin_bottom(12);
5003 tab_thunderbird->set_margin_start(12);
5004 tab_thunderbird->set_margin_end(12);
5005
5006 auto tbInstallInfo = Gtk::make_managed<Gtk::Label>(
5007 _("Installa l'estensione BastionGuard per Thunderbird e il native host.\n"
5008 "Se necessario, inserisci la password amministratore per completare l'installazione.")
5009 );
5010 tbInstallInfo->set_wrap(true);
5011 tbInstallInfo->set_halign(Gtk::Align::START);
5012 tbInstallInfo->set_xalign(0.0f);
5013 tab_thunderbird->append(*tbInstallInfo);
5014
5015 auto tbInstallGrid = Gtk::make_managed<Gtk::Grid>();
5016 tbInstallGrid->set_row_spacing(10);
5017 tbInstallGrid->set_column_spacing(12);
5018
5019 int tbr = 0;
5020
5021 auto lblAdminPw = Gtk::make_managed<Gtk::Label>(_("Password amministratore"));
5022 lblAdminPw->set_halign(Gtk::Align::START);
5023 lblAdminPw->set_xalign(0.0f);
5024
5025 auto eAdminPw = Gtk::make_managed<Gtk::Entry>();
5026 eAdminPw->set_visibility(false);
5027 eAdminPw->set_hexpand(true);
5028 eAdminPw->set_placeholder_text(_("Inserisci la password sudo"));
5029
5030 tbInstallGrid->attach(*lblAdminPw, 0, tbr, 1, 1);
5031 tbInstallGrid->attach(*eAdminPw, 1, tbr, 1, 1);
5032 tbr++;
5033
5034 tab_thunderbird->append(*tbInstallGrid);
5035
5036 auto tbInstallButtons = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
5037
5038 auto btnInstallTbExt = Gtk::make_managed<Gtk::Button>(_("Installa estensione Thunderbird"));
5039 btnInstallTbExt->add_css_class("suggested-action");
5040
5041 auto btnClearTbLog = Gtk::make_managed<Gtk::Button>(_("Pulisci log"));
5042
5043 tbInstallButtons->append(*btnInstallTbExt);
5044 tbInstallButtons->append(*btnClearTbLog);
5045 tab_thunderbird->append(*tbInstallButtons);
5046
5047 auto tbInstallOutput = Gtk::make_managed<Gtk::TextView>();
5048 tbInstallOutput->set_editable(false);
5049 tbInstallOutput->set_cursor_visible(false);
5050 tbInstallOutput->set_monospace(true);
5051 tbInstallOutput->set_wrap_mode(Gtk::WrapMode::WORD_CHAR);
5052 tbInstallOutput->set_vexpand(true);
5053
5054 auto tbInstallBuffer = Gtk::TextBuffer::create();
5055 tbInstallOutput->set_buffer(tbInstallBuffer);
5056
5057 auto tbInstallScroll = Gtk::make_managed<Gtk::ScrolledWindow>();
5058 tbInstallScroll->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
5059 tbInstallScroll->set_min_content_height(260);
5060 tbInstallScroll->set_child(*tbInstallOutput);
5061 tab_thunderbird->append(*tbInstallScroll);
5062
5063 btnClearTbLog->signal_clicked().connect([=]() {
5064 tbInstallBuffer->set_text("");
5065 });
5066
5067 auto run_tb_installer = [=]() {
5068 const std::string script_path =
5069 "/usr/share/BastionGuard/data/extension/bastionguard-tb-extension/install-tb-extension.sh";
5070
5071 tbInstallBuffer->set_text("");
5072
5073 if (!Glib::file_test(script_path, Glib::FileTest::IS_REGULAR)) {
5074 tbInstallBuffer->set_text(
5075 _("Script non trovato:\n") + Glib::ustring(script_path) + "\n"
5076 );
5077 return;
5078 }
5079
5080 const std::string password = std::string(eAdminPw->get_text());
5081
5082 // Password goes only to the child's environment, never to a shell or argv.
5083 // The installer consumes it via sudo -S, and the parent does not log it.
5084 const auto install = bg_process::run({script_path}, true,
5085 8U * 1024U * 1024U, {{"BASTIONGUARD_SUDO_PASSWORD", password}});
5086 if (!install.started) {
5087 tbInstallBuffer->set_text(_("Impossibile avviare lo script di installazione.\n"));
5088 return;
5089 }
5090 const std::string& output = install.output;
5091 const int exit_code = install.exit_code;
5092
5093 if (exit_code == 0) {
5094 tbInstallBuffer->insert(
5095 tbInstallBuffer->end(),
5096 _("\n✔ Installazione Thunderbird completata.\n")
5097 );
5098 } else {
5099 tbInstallBuffer->insert(
5100 tbInstallBuffer->end(),
5101 Glib::ustring::compose(_("\n❌ Installazione fallita (exit=%1)\n"), exit_code)
5102 );
5103 }
5104 };
5105
5106 btnInstallTbExt->signal_clicked().connect([=]() {
5107 run_tb_installer();
5108 });
5109
5110
5111 auto tab_profiles = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
5112 tab_profiles->set_margin_top(12);
5113 tab_profiles->set_margin_bottom(12);
5114 tab_profiles->set_margin_start(12);
5115 tab_profiles->set_margin_end(12);
5116
5117 auto lbl_profiles_info = Gtk::make_managed<Gtk::Label>(
5118 _("Seleziona i profili SMTP da importare da Thunderbird.\n"
5119 "Le password non sono esportabili: dovrai inserirle manualmente dopo l'importazione.")
5120 );
5121 lbl_profiles_info->set_wrap(true);
5122 lbl_profiles_info->set_halign(Gtk::Align::START);
5123 lbl_profiles_info->add_css_class("alert-info");
5124 tab_profiles->append(*lbl_profiles_info);
5125
5126 auto tb_status = Gtk::make_managed<Gtk::Label>();
5127 tb_status->set_halign(Gtk::Align::START);
5128 tb_status->add_css_class("status-muted");
5129 tab_profiles->append(*tb_status);
5130
5131 auto tb_list_frame = Gtk::make_managed<Gtk::Frame>(_("Profili trovati in Thunderbird"));
5132 auto tb_list_box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 6);
5133 tb_list_box->set_margin(8);
5134 tb_list_frame->set_child(*tb_list_box);
5135 tab_profiles->append(*tb_list_frame);
5136
5137 auto tb_found = std::make_shared<std::vector<MailRelayProfile>>();
5138 auto tb_selected = std::make_shared<std::vector<Gtk::CheckButton*>>();
5139
5140 using PwEntriesPtr = std::shared_ptr<std::vector<Gtk::Entry*>>;
5141 auto tb_pw_entries_ref = std::make_shared<PwEntriesPtr>();
5142
5143 using HostEntriesPtr = std::shared_ptr<std::vector<Gtk::Entry*>>;
5144 auto tb_host_entries_ref = std::make_shared<HostEntriesPtr>();
5145
5146 using PortSpinsPtr = std::shared_ptr<std::vector<Gtk::SpinButton*>>;
5147 auto tb_port_spins_ref = std::make_shared<PortSpinsPtr>();
5148
5149 auto populate_profile_list = [=](const std::vector<MailRelayProfile>& source_profiles,
5150 bool from_json) {
5151 for (auto* w : tb_list_box->get_children())
5152 tb_list_box->remove(*w);
5153
5154 tb_found->clear();
5155 tb_selected->clear();
5156
5157 auto tb_pw_entries = std::make_shared<std::vector<Gtk::Entry*>>();
5158 auto tb_host_entries = std::make_shared<std::vector<Gtk::Entry*>>();
5159 auto tb_port_spins = std::make_shared<std::vector<Gtk::SpinButton*>>();
5160
5161 for (size_t i = 0; i < source_profiles.size(); ++i) {
5162 const auto& p = source_profiles[i];
5163 tb_found->push_back(p);
5164
5165 auto row = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 4);
5166 row->set_margin_bottom(10);
5167
5168 if (i == 0 && from_json) {
5169 auto sep_lbl = Gtk::make_managed<Gtk::Label>(_("Profili attivi (da mail.json)"));
5170 sep_lbl->set_halign(Gtk::Align::START);
5171 sep_lbl->add_css_class("caption");
5172 sep_lbl->add_css_class("status-muted");
5173 tb_list_box->append(*sep_lbl);
5174 }
5175
5176 std::string title = p.label + " — " + p.smtp_host + ":" + std::to_string(p.smtp_port);
5177 auto cb = Gtk::make_managed<Gtk::CheckButton>(title);
5178 cb->set_active(true);
5179 if (from_json)
5180 cb->set_sensitive(false);
5181 row->append(*cb);
5182
5183 std::string emails;
5184 for (size_t j = 0; j < p.match_from.size(); ++j) {
5185 if (j) emails += ", ";
5186 emails += p.match_from[j];
5187 }
5188
5189 if (!emails.empty()) {
5190 auto lbl_emails = Gtk::make_managed<Gtk::Label>(
5191 " " + std::string(_("Email: ")) + emails);
5192 lbl_emails->set_halign(Gtk::Align::START);
5193 lbl_emails->set_xalign(0.0f);
5194 lbl_emails->add_css_class("status-muted");
5195 row->append(*lbl_emails);
5196 }
5197
5198 const bool host_is_local = (
5199 p.smtp_host == "127.0.0.1" ||
5200 p.smtp_host == "127.0.0.4" ||
5201 p.smtp_host == "::1" ||
5202 p.smtp_host == "localhost" ||
5203 p.smtp_host.empty()
5204 );
5205
5206 if (host_is_local && !from_json) {
5207 auto lbl_warn = Gtk::make_managed<Gtk::Label>(
5208 "⚠ " + std::string(_("smtp_host non valido — inserisci il server SMTP reale")));
5209 lbl_warn->set_halign(Gtk::Align::START);
5210 lbl_warn->set_margin_start(24);
5211 lbl_warn->add_css_class("alert-warning");
5212 row->append(*lbl_warn);
5213 }
5214
5215 auto host_row = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
5216 host_row->set_margin_start(24);
5217
5218 auto lbl_host = Gtk::make_managed<Gtk::Label>(_("Server SMTP:"));
5219 lbl_host->set_halign(Gtk::Align::START);
5220 lbl_host->set_size_request(100, -1);
5221
5222 auto host_entry = Gtk::make_managed<Gtk::Entry>();
5223 host_entry->set_text(host_is_local ? "" : p.smtp_host);
5224 host_entry->set_placeholder_text(_("es. mail.esempio.it"));
5225 host_entry->set_hexpand(true);
5226
5227 if (host_is_local && !from_json)
5228 host_entry->add_css_class("entry-error");
5229
5230 if (from_json)
5231 host_entry->set_sensitive(!p.smtp_host.empty());
5232
5233 host_row->append(*lbl_host);
5234 host_row->append(*host_entry);
5235
5236 auto lbl_port = Gtk::make_managed<Gtk::Label>(_("Porta:"));
5237 lbl_port->set_halign(Gtk::Align::START);
5238
5239 auto port_spin = Gtk::make_managed<Gtk::SpinButton>();
5240 port_spin->set_range(1, 65535);
5241 port_spin->set_increments(1, 10);
5242 port_spin->set_value(host_is_local ? 587 : (p.smtp_port > 0 ? p.smtp_port : 587));
5243 port_spin->set_size_request(90, -1);
5244
5245 if (from_json)
5246 port_spin->set_sensitive(false);
5247
5248 host_row->append(*lbl_port);
5249 host_row->append(*port_spin);
5250 row->append(*host_row);
5251
5252 auto pw_row = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
5253 pw_row->set_margin_start(24);
5254
5255 auto lbl_pw_label = Gtk::make_managed<Gtk::Label>(_("Password:"));
5256 lbl_pw_label->set_halign(Gtk::Align::START);
5257 lbl_pw_label->set_size_request(100, -1);
5258
5259 auto pw_entry = Gtk::make_managed<Gtk::Entry>();
5260 pw_entry->set_visibility(false);
5261 pw_entry->set_placeholder_text(
5262 from_json ? _("(salvata)") : _("Inserisci la password SMTP")
5263 );
5264 pw_entry->set_hexpand(true);
5265
5266 for (const auto& existing : *profiles) {
5267 if ((existing.id == p.id || existing.smtp_host == p.smtp_host) &&
5268 !existing.password.empty() &&
5269 existing.password != "placeholder") {
5270 pw_entry->set_text(existing.password);
5271 break;
5272 }
5273 }
5274
5275 pw_row->append(*lbl_pw_label);
5276 pw_row->append(*pw_entry);
5277 row->append(*pw_row);
5278
5279 tb_list_box->append(*row);
5280 tb_selected->push_back(cb);
5281 tb_pw_entries->push_back(pw_entry);
5282 tb_host_entries->push_back(host_entry);
5283 tb_port_spins->push_back(port_spin);
5284 }
5285
5286 *tb_pw_entries_ref = tb_pw_entries;
5287 *tb_host_entries_ref = tb_host_entries;
5288 *tb_port_spins_ref = tb_port_spins;
5289 };
5290
5291 {
5292 auto existing_cfg = load_mail_security_config();
5293 if (!existing_cfg.profiles.empty()) {
5294 tb_status->set_text(Glib::ustring::compose(
5295 _("✔ %1 profili attivi"), (int)existing_cfg.profiles.size()));
5296 populate_profile_list(existing_cfg.profiles, true);
5297 }
5298 }
5299
5300 auto btn_scan_tb = Gtk::make_managed<Gtk::Button>(_("🔍 Scansiona Thunderbird"));
5301 btn_scan_tb->add_css_class("suggested-action");
5302 tab_profiles->append(*btn_scan_tb);
5303
5304 btn_scan_tb->signal_clicked().connect([=]() {
5305 std::string err;
5306 auto scanned = tb_import_profiles(err);
5307
5308 if (scanned.empty()) {
5309 tb_status->set_text("❌ " + (err.empty()
5310 ? std::string(_("Nessun profilo trovato"))
5311 : err));
5312 return;
5313 }
5314
5315 tb_status->set_text(Glib::ustring::compose(
5316 _("✔ Trovati %1 profili SMTP da Thunderbird"), (int)scanned.size()));
5317
5318 populate_profile_list(scanned, false);
5319 });
5320
5321 auto btn_import_tb = Gtk::make_managed<Gtk::Button>(_("⬇ Importa profili selezionati"));
5322 tab_profiles->append(*btn_import_tb);
5323
5324 btn_import_tb->signal_clicked().connect([=]() {
5325 if (tb_found->empty()) {
5326 tb_status->set_text(_("❌ Nessun profilo da importare. Scansiona prima."));
5327 return;
5328 }
5329
5330 int imported = 0;
5331 auto& pw_entries = *tb_pw_entries_ref;
5332
5333 for (size_t i = 0; i < tb_found->size() && i < tb_selected->size(); ++i) {
5334 if (!(*tb_selected)[i]->get_active())
5335 continue;
5336
5337 MailRelayProfile src = (*tb_found)[i];
5338
5339 if (pw_entries && i < pw_entries->size()) {
5340 std::string pw = std::string((*pw_entries)[i]->get_text());
5341 if (!pw.empty())
5342 src.password = pw;
5343 }
5344
5345 auto& host_entries = *tb_host_entries_ref;
5346 auto& port_spins = *tb_port_spins_ref;
5347
5348 if (host_entries && i < host_entries->size()) {
5349 std::string h = std::string((*host_entries)[i]->get_text());
5350 auto start = h.find_first_not_of(" \t");
5351 if (start == std::string::npos) {
5352 h.clear();
5353 } else {
5354 auto end = h.find_last_not_of(" \t");
5355 h = h.substr(start, end - start + 1);
5356 }
5357 if (!h.empty())
5358 src.smtp_host = h;
5359 }
5360
5361 if (port_spins && i < port_spins->size()) {
5362 int pt = (*port_spins)[i]->get_value_as_int();
5363 if (pt > 0 && pt < 65536)
5364 src.smtp_port = pt;
5365 }
5366
5367 bool found = false;
5368 for (auto& existing : *profiles) {
5369 if (existing.id == src.id || existing.smtp_host == src.smtp_host) {
5370 existing = src;
5371 found = true;
5372 break;
5373 }
5374 }
5375
5376 if (!found) {
5377 profiles->push_back(src);
5378 if (profiles->size() == 1)
5379 *selected_profile = 0;
5380 }
5381
5382 ++imported;
5383 }
5384
5385 if (imported > 0) {
5386 MailSecurityConfig auto_save = load_mail_security_config();
5387 auto_save.profiles = *profiles;
5388
5389 if (!auto_save.default_profile_id.empty()) {
5390 bool found = false;
5391 for (const auto& p : auto_save.profiles) {
5392 if (p.id == auto_save.default_profile_id) {
5393 found = true;
5394 break;
5395 }
5396 }
5397 if (!found && !auto_save.profiles.empty())
5398 auto_save.default_profile_id = auto_save.profiles[0].id;
5399 } else if (!auto_save.profiles.empty()) {
5400 auto_save.default_profile_id = auto_save.profiles[0].id;
5401 }
5402
5403 if (save_mail_security_config(auto_save)) {
5404 (bg_process::run({"/usr/libexec/bastionguard/bastionguard-service", "--user", "restart", "BastionGuard-mailproxy.service"}).exit_code);
5405 tb_status->set_text(Glib::ustring::compose(
5406 _("✔ %1 profili salvati e proxy riavviato."),
5407 (int)auto_save.profiles.size()));
5408 } else {
5409 tb_status->set_text(Glib::ustring::compose(
5410 _("✔ Importati %1 profili — salvataggio fallito, usa 'Salva' manualmente."),
5411 imported));
5412 }
5413
5414 load_signature_fields();
5415
5416 auto refreshed = load_mail_security_config();
5417 populate_profile_list(
5418 refreshed.profiles.empty() ? *profiles : refreshed.profiles,
5419 true);
5420 } else {
5421 tb_status->set_text(_("Nessun profilo selezionato."));
5422 }
5423 });
5424
5425 tabs->add(*tab_general, "general", _("Generale"));
5426 tabs->add(*tab_signature, "signature", _("Firma"));
5427 tabs->add(*tab_profiles, "smtp-profiles", _("Profili SMTP"));
5428 tabs->add(*tab_thunderbird, "thunderbird", _("Thunderbird"));
5429
5430 inner->append(*tabs_switcher);
5431 inner->append(*tabs);
5432
5433 auto status = Gtk::make_managed<Gtk::Label>();
5434 status->set_halign(Gtk::Align::START);
5435 status->set_xalign(0.0f);
5436 status->add_css_class("status-muted");
5437 inner->append(*status);
5438
5439 auto btnSave = Gtk::make_managed<Gtk::Button>(_("Salva configurazione email"));
5440 btnSave->add_css_class("suggested-action");
5441 btnSave->set_halign(Gtk::Align::START);
5442 inner->append(*btnSave);
5443
5444 btnSave->signal_clicked().connect([=]() {
5445 if (*ui_updating)
5446 return;
5447
5448 save_signature_fields();
5449
5450 MailSecurityConfig out;
5451 out.version = 2;
5452 out.enabled = swEnable->get_active();
5453 out.scan_outgoing = swScan->get_active();
5454 out.inject_signature = swSig->get_active();
5455 out.local_host = cfg.local_host.empty() ? "127.0.0.1" : cfg.local_host;
5456 out.local_port = cfg.local_port > 0 ? cfg.local_port : 2525;
5457 out.local_tls_port = cfg.local_tls_port > 0 ? cfg.local_tls_port : 2465;
5458 out.local_submission_port = cfg.local_submission_port > 0 ? cfg.local_submission_port : 2587;
5459 out.advertise_starttls = swAdvertiseStartTls->get_active();
5460 out.enable_implicit_tls_listener = swImplicitTlsListener->get_active();
5461
5462 MailSignatureConfig sig_ui;
5463 sig_ui.display_name = sName->get_text();
5464 sig_ui.job_title = sRole->get_text();
5465 sig_ui.company = sCompany->get_text();
5466 sig_ui.phone = sPhone->get_text();
5467 sig_ui.website = sWeb->get_text();
5468 sig_ui.logo_path = "/usr/share/BastionGuard/data/logo.png";
5469
5470 if (out.inject_signature) {
5471 if (sig_ui.display_name.empty() &&
5472 sig_ui.job_title.empty() &&
5473 sig_ui.company.empty() &&
5474 sig_ui.phone.empty() &&
5475 sig_ui.website.empty()) {
5476 auto dlg = Gtk::AlertDialog::create(_("Firma vuota"));
5477 dlg->set_detail(_("La firma automatica è abilitata ma tutti i campi firma sono vuoti."));
5478 dlg->show();
5479 return;
5480 }
5481 }
5482
5483 out.profiles = *profiles;
5484
5485 if (out.profiles.empty()) {
5486 MailRelayProfile p;
5487 p.id = "bastionguard";
5488 p.label = "BastionGuard";
5489 p.signature = sig_ui;
5490 out.profiles.push_back(p);
5491 out.default_profile_id = "bastionguard";
5492 } else {
5493 for (auto& p : out.profiles)
5494 p.signature = sig_ui;
5495
5496 std::vector<std::string> loop_profiles;
5497 for (auto& p : out.profiles) {
5498 const std::string h = p.smtp_host;
5499 if (h == "127.0.0.1" || h == "127.0.0.4" || h == "::1" || h == "localhost") {
5500 loop_profiles.push_back(p.label.empty() ? p.id : p.label);
5501 p.smtp_host = "";
5502 }
5503 }
5504
5505 if (!loop_profiles.empty()) {
5506 std::string names;
5507 for (const auto& n : loop_profiles)
5508 names += "• " + n + "\n";
5509
5510 auto dlg = Gtk::AlertDialog::create(_("Profili SMTP non configurati"));
5511 dlg->set_detail(
5512 _("I seguenti profili avevano smtp_host = 127.0.0.1 e non possono essere usati come relay:\n") +
5513 names +
5514 _("\nSono stati salvati senza server SMTP. Aggiorna i campi 'Server SMTP' nel tab Profili SMTP e reimporta.")
5515 );
5516 dlg->show();
5517 }
5518
5519 bool def_found = false;
5520 for (const auto& p : out.profiles) {
5521 if (p.id == out.default_profile_id) {
5522 def_found = true;
5523 break;
5524 }
5525 }
5526 if (!def_found)
5527 out.default_profile_id = out.profiles[0].id;
5528 }
5529
5530 if (!save_mail_security_config(out)) {
5531 status->set_text(_("❌ Impossibile salvare la configurazione"));
5532 auto dlg = Gtk::AlertDialog::create(_("Errore salvataggio"));
5533 dlg->set_detail(_("Impossibile scrivere ~/.config/BastionGuard/mail.json"));
5534 dlg->show();
5535 return;
5536 }
5537
5538 (bg_process::run({"/usr/libexec/bastionguard/bastionguard-service", "--user", "restart", "BastionGuard-mailproxy.service"}).exit_code);
5539
5540 status->set_text(_("✔ Configurazione salvata in ~/.config/BastionGuard/mail.json"));
5541
5542 populate_profile_list(out.profiles, true);
5543 tb_status->set_text(Glib::ustring::compose(
5544 _("✔ %1 profili attivi"), (int)out.profiles.size()));
5545 });
5546
5547 load_signature_fields();
5548
5549 frame->set_child(*inner);
5550 center->append(*frame);
5551 outer->append(*center);
5552 scrolled->set_child(*outer);
5553 page->append(*scrolled);
5554
5555 page_order_.push_back(page);
5556 stack.add(*page, "email", _("Email"));
5557}
static bool save_mail_security_config(const MailSecurityConfig &cfg)
static MailSecurityConfig load_mail_security_config()
static std::vector< MailRelayProfile > tb_import_profiles(std::string &err_out)
MailSignatureConfig signature
std::vector< std::string > match_from
std::string smtp_host
std::string password
std::string default_profile_id
std::vector< MailRelayProfile > profiles
std::string display_name

References _, MailSecurityConfig::advertise_starttls, MailSignatureConfig::company, MailSecurityConfig::default_profile_id, MailSignatureConfig::display_name, MailSecurityConfig::enable_implicit_tls_listener, MailSecurityConfig::enabled, MailRelayProfile::id, MailSecurityConfig::inject_signature, MailSignatureConfig::job_title, MailRelayProfile::label, load_mail_security_config(), MailSecurityConfig::local_host, MailSecurityConfig::local_port, MailSecurityConfig::local_submission_port, MailSecurityConfig::local_tls_port, MailSignatureConfig::logo_path, bg_process::Result::output, page_order_, MailRelayProfile::password, MailSignatureConfig::phone, MailSecurityConfig::profiles, bg_process::run(), save_mail_security_config(), MailSecurityConfig::scan_outgoing, MailRelayProfile::signature, MailRelayProfile::smtp_host, MailRelayProfile::smtp_port, stack, tb_import_profiles(), MailSecurityConfig::version, and MailSignatureConfig::website.

Referenced by SettingsPage().

◆ build_options_tab()

void SettingsPage::build_options_tab ( )
private

Definition at line 2483 of file SettingsPage.cpp.

2483 {
2484 auto page_opts = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
2485
2486 auto frame = Gtk::make_managed<Gtk::Frame>();
2487 frame->get_style_context()->add_class("card");
2488
2489 auto inner = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
2490 inner->set_margin_top(8);
2491 inner->set_margin_bottom(8);
2492 inner->set_margin_start(8);
2493 inner->set_margin_end(8);
2494 auto lblLang = Gtk::make_managed<Gtk::Label>(_("Lingua dell'applicazione"));
2495 lblLang->set_halign(Gtk::Align::START);
2496 inner->append(*lblLang);
2497 auto rowLang = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
2498 auto lblSel = Gtk::make_managed<Gtk::Label>(_("Seleziona lingua"));
2499 lblSel->set_halign(Gtk::Align::START);
2500
2501 combo_language_.set_hexpand(true);
2502 rowLang->append(*lblSel);
2503 rowLang->append(combo_language_);
2504 inner->append(*rowLang);
2505 combo_language_.append("it_IT", "Italiano");
2506 combo_language_.append("en_US", "English");
2507 combo_language_.append("ar_SA", "العربية");
2508 combo_language_.append("de_DE", "Deutsch");
2509 combo_language_.append("es_ES", "Español");
2510 combo_language_.append("fr_FR", "Français");
2511 combo_language_.append("ja_JP", "日本語");
2512 combo_language_.append("nl_NL", "Nederlands");
2513 combo_language_.append("pl_PL", "Polski");
2514 combo_language_.append("pt_PT", "Português");
2515 combo_language_.append("ru_RU", "Русский");
2516 std::string currentLang;
2517 if (const char* v = std::getenv("LC_ALL"); v && *v) currentLang = normalize_locale(v);
2518 else if (const char* v = std::getenv("LC_MESSAGES"); v && *v) currentLang = normalize_locale(v);
2519 else if (const char* v = std::getenv("LANG"); v && *v) currentLang = normalize_locale(v);
2520 if (currentLang.empty()) currentLang = "it_IT";
2521
2522 combo_language_.set_active_id(currentLang);
2523 if (combo_language_.get_active_id() != currentLang) {
2524 combo_language_.set_active_id("en_US");
2525 if (combo_language_.get_active_id() != "en_US")
2526 combo_language_.set_active(0);
2527 }
2528
2529 btn_apply_language_.set_label(_("Applica"));
2530 btn_apply_language_.set_hexpand(false);
2531 inner->append(btn_apply_language_);
2532
2533 btn_apply_language_.signal_clicked().connect([this]() {
2534 std::string lang = combo_language_.get_active_id();
2535 if (lang.empty()) lang = "en_US";
2536
2537 std::string lang_full = lang + ".UTF-8";
2538 std::string lang_short = lang.substr(0, 2);
2539
2540 std::string config_dir = Glib::get_home_dir() + "/.config/BastionGuard";
2541 std::filesystem::create_directories(config_dir);
2542 std::ofstream f(config_dir + "/lang.conf", std::ios::trunc);
2543 if (f.is_open()) {
2544 f << "LANG=" << lang_full << "\n";
2545 f << "LC_ALL=" << lang_full << "\n";
2546 f << "LANGUAGE=" << lang << ":" << lang_short << "\n";
2547 f.close();
2548 std::cout << _("✔ Lingua salvata in ") << config_dir << "/lang.conf\n";
2549 } else {
2550 std::cerr << _("❌ Impossibile salvare ") << config_dir << "/lang.conf\n";
2551 }
2552
2553 auto dialog = Gtk::make_managed<Gtk::Window>();
2554 dialog->set_modal(true);
2555 dialog->set_default_size(280, 120);
2556 dialog->set_title(_("Riavvio dei servizi in corso..."));
2557
2558 auto box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
2559 box->set_margin(20);
2560
2561 auto spinner = Gtk::make_managed<Gtk::Spinner>();
2562 spinner->set_hexpand(true);
2563 spinner->set_vexpand(true);
2564 spinner->start();
2565
2566 auto label = Gtk::make_managed<Gtk::Label>(
2567 _("Attendere qualche secondo, l'app verrà riavviata automaticamente."));
2568 label->set_wrap(true);
2569 label->set_justify(Gtk::Justification::CENTER);
2570
2571 box->append(*spinner);
2572 box->append(*label);
2573 dialog->set_child(*box);
2574 dialog->show();
2575 auto alive = alive_;
2576 std::thread([alive, dialog]() {
2577 const char* alert_service = "BastionGuard-ransomware-alert.service";
2578 const char* scanner_service = "BastionGuard-phishing-scanner.service";
2579 const char* ransomware_service = "BastionGuard-ransomware-scanner.service";
2580 const char* alert_realtime_service = "BastionGuard-ransomware-realtime-alert.service";
2581
2582 const auto restart_user = [](const char* service) {
2583 return bg_process::run({"/usr/libexec/bastionguard/bastionguard-service",
2584 "--user", "restart", service}).ok();
2585 };
2586 for (const auto* unit : {alert_service, alert_realtime_service, ransomware_service}) {
2587 if (!restart_user(unit))
2588 std::cerr << _("[BastionGuard] Impossibile riavviare ") << unit << std::endl;
2589 }
2590 // Do not fall back to pkill -f or nohup with service-derived patterns.
2591 if (!bg_process::run({"pkexec", "/usr/libexec/bastionguard/bastionguard-service",
2592 "--system", "restart", scanner_service}).ok())
2593 std::cerr << _("[BastionGuard] Riavvio servizio di sistema fallito") << std::endl;
2594
2595 std::this_thread::sleep_for(std::chrono::milliseconds(800));
2596
2597 Glib::signal_idle().connect_once([alive, dialog]() {
2598 if (alive && alive->load(std::memory_order_acquire))
2599 dialog->close();
2600 });
2601
2602 char self_path[1024];
2603 ssize_t n = readlink("/proc/self/exe", self_path, sizeof(self_path) - 1);
2604 if (n > 0) {
2605 self_path[n] = '\0';
2606 execl(self_path, self_path, nullptr);
2607 std::cerr << _("❌ Impossibile rilanciare l’app (execl fallito)") << "\n";
2608 } else {
2609 std::cerr << _("❌ Impossibile determinare il percorso dell’eseguibile") << "\n";
2610 }
2611 }).detach();
2612
2613 });
2614
2615
2616 frame->set_child(*inner);
2617 page_opts->append(*frame);
2618
2619
2620 {
2621 auto frameTheme = Gtk::make_managed<Gtk::Frame>();
2622 frameTheme->get_style_context()->add_class("card");
2623
2624 auto innerTheme = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
2625 innerTheme->set_margin_top(8);
2626 innerTheme->set_margin_bottom(8);
2627 innerTheme->set_margin_start(8);
2628 innerTheme->set_margin_end(8);
2629
2630 auto lblTheme = Gtk::make_managed<Gtk::Label>(_("Tema dell'interfaccia"));
2631 lblTheme->set_halign(Gtk::Align::START);
2632 innerTheme->append(*lblTheme);
2633
2634 auto rowTheme = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
2635
2636 auto lblThemeSel = Gtk::make_managed<Gtk::Label>(_("Seleziona tema"));
2637 lblThemeSel->set_halign(Gtk::Align::START);
2638
2639 auto* combo_theme = Gtk::make_managed<Gtk::ComboBoxText>();
2640 combo_theme->set_hexpand(true);
2641 combo_theme->append("light", _("☀ Chiaro (Light)"));
2642 combo_theme->append("dark", _("🌙 Scuro (Dark)"));
2643
2644 {
2645 std::string themeCfg = Glib::get_home_dir() + "/.config/BastionGuard/theme.conf";
2646 std::ifstream tf(themeCfg);
2647 std::string saved;
2648 if (tf >> saved && (saved == "light" || saved == "dark"))
2649 combo_theme->set_active_id(saved);
2650 else
2651 combo_theme->set_active_id("light");
2652 }
2653
2654 rowTheme->append(*lblThemeSel);
2655 rowTheme->append(*combo_theme);
2656 innerTheme->append(*rowTheme);
2657
2658 auto lblPreview = Gtk::make_managed<Gtk::Label>("");
2659 lblPreview->set_halign(Gtk::Align::START);
2660 lblPreview->get_style_context()->add_class("dim-label");
2661 innerTheme->append(*lblPreview);
2662
2663 auto updatePreview = [lblPreview](const std::string& id) {
2664 if (id == "dark")
2665 lblPreview->set_text(_("Tema scuro: sfondo #1a1d23, testo chiaro."));
2666 else
2667 lblPreview->set_text(_("Tema chiaro: sfondo #f8f9fa, testo scuro."));
2668 };
2669 updatePreview(combo_theme->get_active_id());
2670 combo_theme->signal_changed().connect([combo_theme, updatePreview]() {
2671 updatePreview(combo_theme->get_active_id());
2672 });
2673
2674 auto* btn_apply_theme = Gtk::make_managed<Gtk::Button>(_("Applica tema"));
2675 btn_apply_theme->set_hexpand(false);
2676 innerTheme->append(*btn_apply_theme);
2677
2678 btn_apply_theme->signal_clicked().connect([this, combo_theme]() {
2679 const std::string themeId = combo_theme->get_active_id();
2680 if (themeId.empty()) return;
2681
2682
2683 std::string cfgDir = Glib::get_home_dir() + "/.config/BastionGuard";
2684 std::filesystem::create_directories(cfgDir);
2685 std::ofstream tf(cfgDir + "/theme.conf", std::ios::trunc);
2686 tf << themeId;
2687 tf.close();
2688
2689
2690 std::string cssFile;
2691 if (themeId == "dark")
2692 cssFile = Glib::build_filename(DATA_DIR, "BastionGuard-dark.css");
2693 else
2694 cssFile = Glib::build_filename(DATA_DIR, "BastionGuard.css");
2695
2696 if (!std::filesystem::exists(cssFile)) {
2697 char self_path[1024] = {};
2698 ssize_t n = readlink("/proc/self/exe", self_path, sizeof(self_path) - 1);
2699 if (n > 0) {
2700 std::string exeDir = std::filesystem::path(self_path).parent_path().string();
2701 std::string candidate = exeDir + "/" +
2702 (themeId == "dark" ? "BastionGuard-dark.css" : "BastionGuard.css");
2703 if (std::filesystem::exists(candidate))
2704 cssFile = candidate;
2705 }
2706 }
2707
2708 if (!std::filesystem::exists(cssFile)) {
2709 Gtk::Window* pw = dynamic_cast<Gtk::Window*>(get_root());
2711 _("File CSS non trovato:\n") + cssFile,
2712 Gtk::MessageType::ERROR);
2713 return;
2714 }
2715
2716 try {
2717 auto provider = Gtk::CssProvider::create();
2718 provider->load_from_path(cssFile);
2719 Gtk::StyleContext::add_provider_for_display(
2720 Gdk::Display::get_default(),
2721 provider,
2722 GTK_STYLE_PROVIDER_PRIORITY_USER);
2723
2724 std::cout << "[BastionGuard] Tema applicato: " << cssFile << std::endl;
2725
2726 Gtk::Window* pw = dynamic_cast<Gtk::Window*>(get_root());
2728 _("Tema applicato con successo.\n"
2729 "Per un'applicazione completa riavvia BastionGuard."),
2730 Gtk::MessageType::INFO);
2731
2732 } catch (const Glib::Error& e) {
2733 std::cerr << "[BastionGuard] Errore CSS: " << e.what() << std::endl;
2734 Gtk::Window* pw = dynamic_cast<Gtk::Window*>(get_root());
2736 (Glib::ustring(_("Errore nel caricamento del tema:\n")) + e.what()).raw(),
2737 Gtk::MessageType::ERROR);
2738 }
2739 });
2740
2741 frameTheme->set_child(*innerTheme);
2742 page_opts->append(*frameTheme);
2743 }
2744
2745 auto frameWeb = Gtk::make_managed<Gtk::Frame>();
2746 frameWeb->get_style_context()->add_class("card");
2747
2748 auto innerWeb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
2749 innerWeb->set_margin(10);
2750
2751 auto lblSystem = Gtk::make_managed<Gtk::Label>(_("Sistema operativo / Distro"));
2752 lblSystem->set_halign(Gtk::Align::START);
2753 innerWeb->append(*lblSystem);
2754
2755 combo_os_.append("auto", _("Rilevamento automatico"));
2756 combo_os_.append("debian", "Debian / Ubuntu / Mint");
2757 combo_os_.append("fedora", "Fedora / RHEL / CentOS / Alma / Rocky");
2758 combo_os_.append("arch", "Arch / Manjaro / Endeavour");
2759 combo_os_.append("opensuse", "openSUSE / SLE");
2760 combo_os_.append("gentoo", "Gentoo");
2761 combo_os_.append("slackware", "Slackware");
2762 combo_os_.append("bsd", "FreeBSD / OpenBSD / NetBSD");
2763 combo_os_.set_active_id(detect_distro());
2764 innerWeb->append(combo_os_);
2765
2766 auto gridPorts = Gtk::make_managed<Gtk::Grid>();
2767 gridPorts->set_row_spacing(6);
2768 gridPorts->set_column_spacing(6);
2769
2770 auto lblHttp = Gtk::make_managed<Gtk::Label>("Porta HTTP:");
2771 lblHttp->set_halign(Gtk::Align::START);
2772 auto [saved_http, saved_https] = read_webports_conf();
2773 entry_http_port_.set_placeholder_text("81");
2774 entry_http_port_.set_width_chars(6);
2775 entry_http_port_.set_max_width_chars(6);
2776 entry_http_port_.set_text(std::to_string(saved_http));
2777
2778 auto lblHttps = Gtk::make_managed<Gtk::Label>("Porta HTTPS:");
2779 lblHttps->set_halign(Gtk::Align::START);
2780 entry_https_port_.set_placeholder_text("444");
2781 entry_https_port_.set_width_chars(6);
2782 entry_https_port_.set_max_width_chars(6);
2783 entry_https_port_.set_text(std::to_string(saved_https));
2784
2785 gridPorts->attach(*lblHttp, 0, 0, 1, 1);
2786 gridPorts->attach(entry_http_port_, 1, 0, 1, 1);
2787 gridPorts->attach(*lblHttps, 0, 1, 1, 1);
2788 gridPorts->attach(entry_https_port_, 1, 1, 1, 1);
2789 innerWeb->append(*gridPorts);
2790
2791 btn_apply_webconfig_.set_label(_("Applica configurazione web"));
2792 innerWeb->append(btn_apply_webconfig_);
2793
2794 auto write_temp_script_and_elevate = [](const std::string& script_contents, std::string* out_log = nullptr) -> bool {
2795 char tmpl[] = "/tmp/BastionGuard_tmp_XXXXXX";
2796 int fd = mkstemp(tmpl);
2797 if (fd < 0) return false;
2798
2799 std::string tmpname = tmpl;
2800 FILE* f = fdopen(fd, "w");
2801 if (!f) { close(fd); return false; }
2802 fputs(script_contents.c_str(), f);
2803 fclose(f);
2804 chmod(tmpname.c_str(), 0755);
2805
2806 const std::string runner = std::filesystem::exists("/usr/bin/pkexec") ? "pkexec" : "sudo";
2807 std::map<std::string, std::string> env;
2808 for (const char* key : {"DISPLAY", "XAUTHORITY", "DBUS_SESSION_BUS_ADDRESS"}) {
2809 if (const char* val = std::getenv(key)) env.emplace(key, val);
2810 }
2811 const auto result = bg_process::run({runner, tmpname}, true, 8U * 1024U * 1024U, env);
2812 const std::string& output = result.output;
2813 std::filesystem::remove(tmpname);
2814 if (out_log) *out_log = output;
2815 return result.ok();
2816 };
2817
2818 auto replace_placeholders = [](const std::string& src, const std::string& dest,
2819 int http_port, int https_port) -> bool {
2820 std::ifstream in(src);
2821 std::ofstream out(dest);
2822 if (!in.is_open() || !out.is_open()) return false;
2823 std::string line;
2824 while (std::getline(in, line)) {
2825 line = std::regex_replace(line, std::regex("\\{\\{HTTP_PORT\\}\\}"), std::to_string(http_port));
2826 line = std::regex_replace(line, std::regex("\\{\\{HTTPS_PORT\\}\\}"), std::to_string(https_port));
2827 out << line << "\n";
2828 }
2829 return true;
2830 };
2831
2832 btn_apply_webconfig_.signal_clicked().connect([this, replace_placeholders, write_temp_script_and_elevate]() {
2833 namespace fs = std::filesystem;
2834
2835 Gtk::Window* parent = dynamic_cast<Gtk::Window*>(get_root());
2836 auto show_message = [parent](const Glib::ustring& msg, Gtk::MessageType type, const Glib::ustring& /*title*/) {
2837 Utils::show_message(parent, msg.raw(), type);
2838 };
2839
2840 std::string distro = combo_os_.get_active_id();
2841 if (distro.empty() || distro == "auto")
2842 distro = detect_distro();
2843
2844 std::cout << _("[BastionGuard] Distro rilevata: ") << distro << std::endl;
2845
2846 int http_port = 81, https_port = 444;
2847 try {
2848 http_port = std::stoi(entry_http_port_.get_text());
2849 https_port = std::stoi(entry_https_port_.get_text());
2850 } catch (...) {
2851 show_message(_("Le porte devono essere numeriche valide."),
2852 Gtk::MessageType::ERROR, _("BastionGuard - Errore"));
2853 return;
2854 }
2855
2856 if (http_port <= 0 || http_port >= 65536 ||
2857 https_port <= 0 || https_port >= 65536) {
2858 show_message(_("Le porte devono essere comprese tra 1 e 65535."),
2859 Gtk::MessageType::ERROR, _("BastionGuard - Errore"));
2860 return;
2861 }
2862
2863 std::string template_path = Glib::build_filename(DATA_DIR, "vhosts/nginx.conf");
2864 std::string tmpfile = "/tmp/BastionGuard_nginx.conf";
2865 if (!replace_placeholders(template_path, tmpfile, http_port, https_port)) {
2866 show_message(_("Errore durante la sostituzione delle porte nel template."),
2867 Gtk::MessageType::ERROR, _("BastionGuard - Errore"));
2868 return;
2869 }
2870
2871 std::string nginx_default_src;
2872 if (distro == "arch" || distro == "manjaro" || distro == "endeavour") {
2873 nginx_default_src = Glib::build_filename(DATA_DIR, "vhosts/nginx-config-arch.conf");
2874 } else {
2875 nginx_default_src = Glib::build_filename(DATA_DIR, "vhosts/nginx-default.conf");
2876 }
2877 std::string target_conf, site_avail, site_enable;
2878 if (distro == "arch" || distro == "manjaro" || distro == "endeavour") {
2879 site_avail = "/etc/nginx/sites-available/default";
2880 site_enable = "/etc/nginx/sites-enabled/default";
2881 target_conf = site_avail;
2882 } else {
2883 target_conf = fs::exists("/etc/nginx/conf.d")
2884 ? "/etc/nginx/conf.d/BastionGuard.conf"
2885 : "/etc/nginx/sites-enabled/BastionGuard.conf";
2886 }
2887
2888 std::ostringstream script;
2889 script << "#!/bin/sh\nset -e\n";
2890 script << _("echo '[BastionGuard] Applicazione configurazione NGINX...'\n");
2891 script << "mkdir -p /etc/BastionGuard\n";
2892 script << "echo \"" << http_port << " " << https_port << "\" > /etc/BastionGuard/webports.conf\n";
2893
2894 if (distro == "arch" || distro == "manjaro" || distro == "endeavour") {
2895 script << "mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled\n";
2896 script << "echo '[BastionGuard] Installo configurazione Arch...'\n";
2897 script << "install -m 0644 " << nginx_default_src << " " << site_avail << "\n";
2898 script << "ln -sf " << site_avail << " " << site_enable << "\n";
2899 } else {
2900 script << _("echo '[BastionGuard] Verifica configurazione esistente...'\n");
2901 script << "if ! grep -q 'BastionGuard Local Web Server' /etc/nginx/nginx.conf 2>/dev/null; then\n";
2902 script << " echo '[BastionGuard] Inserisco blocco mancante in nginx.conf...'\n";
2903 script << " cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak\n";
2904 script << " cat " << nginx_default_src << " >> /etc/nginx/nginx.conf\n";
2905 script << "else\n";
2906 script << _(" echo '[BastionGuard] Configurazione già presente, aggiornamento non necessario.'\n");
2907 script << "fi\n";
2908 script << "install -m 0644 " << tmpfile << " " << target_conf << "\n";
2909 }
2910
2911 script << "nginx -t && /usr/libexec/bastionguard/bastionguard-service --system restart nginx.service\n";
2912
2913 std::string out;
2914 if (!write_temp_script_and_elevate(script.str(), &out)) {
2915 std::cerr << _("[BastionGuard] Fallito:\n") << out << std::endl;
2916 show_message(_("Errore durante l’applicazione della configurazione:\n") + out,
2917 Gtk::MessageType::ERROR, _("BastionGuard - Errore"));
2918 return;
2919 }
2920
2921 show_message(_("Configurazione NGINX aggiornata e servizio riavviato."),
2922 Gtk::MessageType::INFO, _("BastionGuard - Esito"));
2923 });
2924
2925 frameWeb->set_child(*innerWeb);
2926 page_opts->append(*frameWeb);
2927
2928 page_order_.push_back(page_opts);
2929 stack.add(*page_opts, "options", _("Opzioni"));
2930}
Gtk::Button btn_apply_language_
Gtk::ComboBoxText combo_os_
Gtk::Entry entry_http_port_
Gtk::ComboBoxText combo_language_
Gtk::Entry entry_https_port_
Gtk::Button btn_apply_webconfig_
static void show_message(Gtk::Window *parent, const std::string &message, Gtk::MessageType type=Gtk::MessageType::INFO, const std::string &secondary=std::string())
Definition Utils.cpp:33
#define DATA_DIR
Definition Resource.hpp:28
std::pair< int, int > read_webports_conf()
static bool write_temp_script_and_elevate(const std::string &script_contents, std::string *out_log=nullptr, int *exit_code=nullptr)
static std::string normalize_locale(std::string s)
std::string detect_distro()

References _, alive_, btn_apply_language_, btn_apply_webconfig_, combo_language_, combo_os_, DATA_DIR, detect_distro(), entry_http_port_, entry_https_port_, normalize_locale(), bg_process::Result::ok(), bg_process::Result::output, page_order_, read_webports_conf(), bg_process::run(), Utils::show_message(), stack, and write_temp_script_and_elevate().

Referenced by SettingsPage().

◆ build_proxy_bypass_tab()

void SettingsPage::build_proxy_bypass_tab ( )
private

Definition at line 3941 of file SettingsPage.cpp.

3941 {
3942 auto page = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
3943 page->set_margin(12);
3944 auto frame = Gtk::make_managed<Gtk::Frame>();
3945 auto inner = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
3946 inner->set_margin(10);
3947
3948 auto lblTitle = Gtk::make_managed<Gtk::Label>(_("🔓 Bypass Proxy"));
3949 lblTitle->set_halign(Gtk::Align::START);
3950 lblTitle->add_css_class("card-title");
3951 inner->append(*lblTitle);
3952
3953 auto lblDesc = Gtk::make_managed<Gtk::Label>(
3954 _("Domini, indirizzi IP e range CIDR in questa lista bypassano completamente il proxy BastionGuard.\n"
3955 "Il traffico viene inoltrato in tunnel TCP puro trasparente: nessuna\n"
3956 "intercettazione TLS, nessuna sostituzione certificati.\n\n"
3957 "Formati accettati:\n"
3958 " • dominio: banca.it, checkout.esempio.com\n"
3959 " • IPv4: 1.1.1.1\n"
3960 " • IPv6: 2001:db8::1\n"
3961 " • CIDR: 1.1.1.0/24, 2a01:4f8::/29\n\n"
3962 "Usare per siti che attivano 2FA o CAPTCHA quando rilevano la presenza del proxy.")
3963 );
3964 lblDesc->set_wrap(true);
3965 lblDesc->set_halign(Gtk::Align::START);
3966 lblDesc->add_css_class("card-description");
3967 inner->append(*lblDesc);
3968
3969 auto lblInfo = Gtk::make_managed<Gtk::Label>(
3970 _("ℹ️ Anche le banche presenti in banks.json vengono bypassate se inserite qui.\n"
3971 "Rimuoverle dal bypass per ripristinare la protezione sandbox.")
3972 );
3973 lblInfo->set_wrap(true);
3974 lblInfo->set_halign(Gtk::Align::START);
3975 lblInfo->add_css_class("alert-info");
3976 inner->append(*lblInfo);
3977
3978 auto lblList = Gtk::make_managed<Gtk::Label>(_("Domini in bypass:"));
3979 lblList->set_halign(Gtk::Align::START);
3980 inner->append(*lblList);
3981
3982 auto store = Gio::ListStore<Gtk::StringObject>::create();
3983 auto selection = Gtk::SingleSelection::create(store);
3984
3985 auto factory = Gtk::SignalListItemFactory::create();
3986 factory->signal_setup().connect([](const Glib::RefPtr<Gtk::ListItem>& item) {
3987 auto lbl = Gtk::make_managed<Gtk::Label>();
3988 lbl->set_xalign(0.0);
3989 lbl->set_margin(6);
3990 item->set_child(*lbl);
3991 });
3992 factory->signal_bind().connect([](const Glib::RefPtr<Gtk::ListItem>& item) {
3993 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(item->get_item());
3994 if (auto lbl = dynamic_cast<Gtk::Label*>(item->get_child()))
3995 lbl->set_text(obj ? obj->get_string() : "");
3996 });
3997
3998 auto listView = Gtk::make_managed<Gtk::ListView>(selection, factory);
3999 listView->set_vexpand(true);
4000 listView->set_can_focus(true);
4001 listView->add_css_class("whitelist-view");
4002
4003 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
4004 scrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
4005 scrolled->set_expand(true);
4006 scrolled->set_min_content_height(160);
4007 scrolled->set_child(*listView);
4008 inner->append(*scrolled);
4009
4010 auto reload_from_file = [store]() {
4011 store->remove_all();
4012 for (const auto& d : load_proxy_bypass_domains())
4013 store->append(Gtk::StringObject::create(d));
4014 };
4015 reload_from_file();
4016
4017 auto entry = Gtk::make_managed<Gtk::Entry>();
4018 entry->set_placeholder_text(_("dominio (banca.it), IP (1.1.1.1) o CIDR (1.1.1.0/24)"));
4019 entry->set_hexpand(true);
4020 entry->add_css_class("whitelist-entry");
4021
4022 auto btnAdd = Gtk::make_managed<Gtk::Button>(_("Aggiungi"));
4023 auto btnRemove = Gtk::make_managed<Gtk::Button>(_("Rimuovi"));
4024 auto btnReload = Gtk::make_managed<Gtk::Button>(_("Ripristina"));
4025 auto btnSave = Gtk::make_managed<Gtk::Button>(_("Salva"));
4026 btnSave->add_css_class("btn-primary");
4027
4028 auto lblStatus = Gtk::make_managed<Gtk::Label>();
4029 lblStatus->set_halign(Gtk::Align::START);
4030
4031 auto rowBtns = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
4032 rowBtns->append(*entry);
4033 rowBtns->append(*btnAdd);
4034 rowBtns->append(*btnRemove);
4035 rowBtns->append(*btnReload);
4036 rowBtns->append(*btnSave);
4037 inner->append(*rowBtns);
4038 inner->append(*lblStatus);
4039
4040 auto show_alert_bypass = [this](const Glib::RefPtr<Gtk::AlertDialog>& dlg) {
4041 if (auto* root = this->get_root())
4042 if (auto* win = dynamic_cast<Gtk::Window*>(root)) {
4043 dlg->show(*win); return;
4044 }
4045 dlg->show();
4046 };
4047
4048 btnAdd->signal_clicked().connect([store, entry, lblStatus, show_alert_bypass]() {
4049 std::string s = entry->get_text();
4050
4051 // Strip schema https:// http:// se presente
4052 auto p = s.find("://");
4053 if (p != std::string::npos) s = s.substr(p + 3);
4054
4055 // Per IPv6 con bracket eventuali "[::1]:443" → strip della porta DOPO ]
4056 // Per dominio/IPv4 strip del path "/foo" e della porta ":443"
4057 if (!s.empty() && s.front() == '[') {
4058 auto rb = s.find(']');
4059 if (rb != std::string::npos) {
4060 // tieni "[...]" pulito, scarta tutto dopo ]
4061 s = s.substr(0, rb + 1);
4062 }
4063 } else {
4064 // Path
4065 auto sl = s.find('/');
4066 // Una "/" può essere parte di un CIDR (es. "1.2.3.0/24"). Per
4067 // capire se è path o CIDR: dopo lo / ci sono solo digit?
4068 if (sl != std::string::npos) {
4069 std::string after = s.substr(sl + 1);
4070 bool only_digits = !after.empty();
4071 for (char c : after)
4072 if (!std::isdigit(static_cast<unsigned char>(c))) { only_digits = false; break; }
4073 if (!only_digits) s = s.substr(0, sl);
4074 }
4075 // Porta ":443" — solo se NON è un IPv6 (che ha tanti ":")
4076 if (std::count(s.begin(), s.end(), ':') == 1) {
4077 auto col = s.find(':');
4078 s = s.substr(0, col);
4079 }
4080 }
4081
4082 // Trim whitespace
4083 while (!s.empty() && std::isspace(static_cast<unsigned char>(s.front()))) s.erase(s.begin());
4084 while (!s.empty() && std::isspace(static_cast<unsigned char>(s.back()))) s.pop_back();
4085
4086 // I domini DNS sono case-insensitive, gli IPv6 letterali sì (per-RFC),
4087 // gli IPv4 e i CIDR contengono solo digit/. quindi il tolower non li tocca.
4088 std::transform(s.begin(), s.end(), s.begin(),
4089 [](unsigned char c){ return static_cast<char>(std::tolower(c)); });
4090
4091 const BypassKind kind = classify_bypass_entry(s);
4092 if (kind == BypassKind::Invalid) {
4093 auto dlg = Gtk::AlertDialog::create(_("Valore non valido"));
4094 dlg->set_detail(_("Formato non riconosciuto.\n\n"
4095 "Esempi accettati:\n"
4096 " • banca.it\n"
4097 " • checkout.esempio.com\n"
4098 " • 93.55.84.43\n"
4099 " • 2001:db8::1\n"
4100 " • 93.55.84.0/24"));
4101 show_alert_bypass(dlg);
4102 return;
4103 }
4104
4105 // Anti-duplicati
4106 for (guint i = 0; i < store->get_n_items(); ++i) {
4107 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(store->get_object(i));
4108 if (obj && obj->get_string() == s) { entry->set_text(""); return; }
4109 }
4110 store->append(Gtk::StringObject::create(s));
4111 entry->set_text("");
4112
4113 const char* kind_name = "?";
4114 switch (kind) {
4115 case BypassKind::Domain: kind_name = "dominio"; break;
4116 case BypassKind::IPv4: kind_name = "IPv4"; break;
4117 case BypassKind::IPv6: kind_name = "IPv6"; break;
4118 case BypassKind::CIDR: kind_name = "CIDR"; break;
4119 case BypassKind::Invalid: break;
4120 }
4121 char buf[256];
4122 std::snprintf(buf, sizeof(buf),
4123 _("➕ %s aggiunto — clicca Salva per applicare."), kind_name);
4124 lblStatus->set_text(buf);
4125 lblStatus->remove_css_class("status-ok");
4126 lblStatus->add_css_class("status-muted");
4127 });
4128
4129 btnRemove->signal_clicked().connect([selection, store, lblStatus]() {
4130 guint pos = selection->get_selected();
4131 if (pos != GTK_INVALID_LIST_POSITION) {
4132 store->remove(pos);
4133 lblStatus->set_text(_("🗑 Dominio rimosso — clicca Salva per applicare."));
4134 lblStatus->remove_css_class("status-ok");
4135 lblStatus->add_css_class("status-muted");
4136 }
4137 });
4138
4139 btnReload->signal_clicked().connect([reload_from_file, lblStatus]() {
4140 reload_from_file();
4141 lblStatus->set_text(_("↩️ Lista ripristinata dal file."));
4142 lblStatus->remove_css_class("status-ok");
4143 lblStatus->add_css_class("status-muted");
4144 });
4145
4146 btnSave->signal_clicked().connect([store, lblStatus, show_alert_bypass]() {
4147 std::vector<std::string> domains;
4148 domains.reserve(store->get_n_items());
4149 for (guint i = 0; i < store->get_n_items(); ++i) {
4150 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(store->get_object(i));
4151 if (obj) domains.push_back(obj->get_string());
4152 }
4153 if (!save_proxy_bypass_domains(domains)) {
4154 auto dlg = Gtk::AlertDialog::create(_("Errore"));
4155 dlg->set_detail(_("Impossibile salvare proxy_bypass.json."));
4156 show_alert_bypass(dlg);
4157 return;
4158 }
4159 lblStatus->set_text(_("✔ proxy_bypass.json salvato"));
4160 lblStatus->remove_css_class("status-muted");
4161 lblStatus->add_css_class("status-ok");
4162 // Riavvia il servizio CEF solo nelle build/distribuzioni che lo supportano.
4164 std::thread([]() {
4165 (bg_process::run({"/usr/libexec/bastionguard/bastionguard-service", "--user", "restart", "BastionGuard-cef.service"}).exit_code);
4166 }).detach();
4167 }
4168 });
4169
4170 frame->set_child(*inner);
4171 page->append(*frame);
4172 page_order_.push_back(page);
4173 stack.add(*page, "proxy-bypass", _("Bypass Proxy"));
4174}
BypassKind
static BypassKind classify_bypass_entry(const std::string &s_in)
static bool save_proxy_bypass_domains(const std::vector< std::string > &domains)
static std::vector< std::string > load_proxy_bypass_domains()

References _, BastionGuard::Platform::cef_available(), CIDR, classify_bypass_entry(), Domain, Invalid, IPv4, IPv6, load_proxy_bypass_domains(), page_order_, bg_process::run(), save_proxy_bypass_domains(), and stack.

Referenced by SettingsPage().

◆ build_secure_payments_tab()

void SettingsPage::build_secure_payments_tab ( )
private

Definition at line 3442 of file SettingsPage.cpp.

3442 {
3444
3445 auto page_pay = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
3446 page_pay->set_margin(12);
3447
3448 auto framePay = Gtk::make_managed<Gtk::Frame>();
3449
3450 auto innerPay = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
3451 innerPay->set_margin_top(10);
3452 innerPay->set_margin_bottom(10);
3453 innerPay->set_margin_start(10);
3454 innerPay->set_margin_end(10);
3455
3456 auto run_cmd_capture = [](const std::vector<std::string>& argv,
3457 std::string* stdout_out = nullptr,
3458 std::string* stderr_out = nullptr) -> bool
3459 {
3460 try {
3461 auto proc = Gio::Subprocess::create(
3462 argv,
3463 Gio::Subprocess::Flags::STDOUT_PIPE |
3464 Gio::Subprocess::Flags::STDERR_PIPE
3465 );
3466
3467 auto [stdout_str, stderr_str] = proc->communicate_utf8("");
3468 if (stdout_out) *stdout_out = stdout_str.raw();
3469 if (stderr_out) *stderr_out = stderr_str.raw();
3470
3471 return proc->get_successful();
3472 } catch (const std::exception& ex) {
3473 if (stderr_out) *stderr_out = ex.what();
3474 return false;
3475 } catch (...) {
3476 if (stderr_out) *stderr_out = "Eccezione sconosciuta";
3477 return false;
3478 }
3479 };
3480
3481 auto resolve_ca_path = []() -> std::string
3482 {
3483 const auto user_ca = Glib::build_filename(
3484 Glib::get_home_dir(),
3485 ".local", "share", "BastionGuard", "certs", "intercept-ca.crt.pem");
3486
3487 if (std::filesystem::exists(user_ca))
3488 return user_ca;
3489
3490 const std::string system_ca = "/etc/BastionGuard/certs/intercept-ca.crt.pem";
3491 if (std::filesystem::exists(system_ca))
3492 return system_ca;
3493
3494 return {};
3495 };
3496
3497 auto show_alert = [this](const Glib::RefPtr<Gtk::AlertDialog>& dlg) {
3498 if (auto* root = this->get_root()) {
3499 if (auto* win = dynamic_cast<Gtk::Window*>(root)) {
3500 dlg->show(*win);
3501 return;
3502 }
3503 }
3504 dlg->show();
3505 };
3506
3507 auto lblPayTitle = Gtk::make_managed<Gtk::Label>(_("Pagamenti Sicuri (CEF)"));
3508 lblPayTitle->set_halign(Gtk::Align::START);
3509 lblPayTitle->add_css_class("card-title");
3510 innerPay->append(*lblPayTitle);
3511
3512
3513 auto lblPayDesc = Gtk::make_managed<Gtk::Label>(
3514 _("Questa opzione apre in sandbox CEF delle pagine tipiche di pagamento "
3515 "(checkout, gateway, 3D Secure)\n\n"
3516 "Consigliato per acquisti online e inserimento dati carta.")
3517 );
3518 lblPayDesc->set_wrap(true);
3519 lblPayDesc->set_halign(Gtk::Align::START);
3520 lblPayDesc->add_css_class("card-description");
3521 innerPay->append(*lblPayDesc);
3522
3523 auto lblPayInfo = Gtk::make_managed<Gtk::Label>(
3524 _("ℹ️ I pagamenti sicuri utilizzano un browser isolato (CEF sandbox) "
3525 "per ridurre il rischio di furto di credenziali e dati di pagamento.\n"
3526 "Questa modalità non modifica il funzionamento del sito e non salva "
3527 "alcuna informazione sensibile.")
3528 );
3529 lblPayInfo->set_wrap(true);
3530 lblPayInfo->set_halign(Gtk::Align::START);
3531 lblPayInfo->add_css_class("alert-info");
3532 innerPay->append(*lblPayInfo);
3533
3534 auto lblPayToggle = Gtk::make_managed<Gtk::Label>(_("Abilita pagamenti sicuri"));
3535 lblPayToggle->set_halign(Gtk::Align::START);
3536
3537 auto swPay = Gtk::make_managed<Gtk::Switch>();
3538 swPay->set_halign(Gtk::Align::END);
3539 swPay->set_active(SettingsStore::get_secure_payments_enabled());
3540
3541 auto rowPay = Gtk::make_managed<Gtk::CenterBox>();
3542 rowPay->set_start_widget(*lblPayToggle);
3543 rowPay->set_end_widget(*swPay);
3544 innerPay->append(*rowPay);
3545
3546 auto lblPayStatus = Gtk::make_managed<Gtk::Label>();
3547 lblPayStatus->set_halign(Gtk::Align::START);
3548 innerPay->append(*lblPayStatus);
3549
3550 auto refreshPayStatus = [lblPayStatus, swPay]() {
3551 lblPayStatus->set_text(
3552 swPay->get_active()
3553 ? _("✔ Pagamenti sicuri: abilitati")
3554 : _("ℹ️ Pagamenti sicuri: disabilitati")
3555 );
3556 lblPayStatus->remove_css_class("status-ok");
3557 lblPayStatus->remove_css_class("status-muted");
3558 lblPayStatus->add_css_class(swPay->get_active() ? "status-ok" : "status-muted");
3559 };
3560 refreshPayStatus();
3561
3562 auto lblList = Gtk::make_managed<Gtk::Label>(_("Domini/URL per Pagamenti Sicuri"));
3563 lblList->set_halign(Gtk::Align::START);
3564 innerPay->append(*lblList);
3565
3566 auto store = Gio::ListStore<Gtk::StringObject>::create();
3567 auto selection = Gtk::SingleSelection::create(store);
3568
3569 auto factory = Gtk::SignalListItemFactory::create();
3570 factory->signal_setup().connect([](const Glib::RefPtr<Gtk::ListItem>& item) {
3571 auto lbl = Gtk::make_managed<Gtk::Label>();
3572 lbl->set_xalign(0.0);
3573 lbl->set_margin(6);
3574 item->set_child(*lbl);
3575 });
3576 factory->signal_bind().connect([](const Glib::RefPtr<Gtk::ListItem>& item) {
3577 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(item->get_item());
3578 if (auto lbl = dynamic_cast<Gtk::Label*>(item->get_child()))
3579 lbl->set_text(obj ? obj->get_string() : "");
3580 });
3581
3582 auto listView = Gtk::make_managed<Gtk::ListView>(selection, factory);
3583 listView->set_vexpand(true);
3584 listView->set_can_focus(true);
3585 listView->add_css_class("whitelist-view");
3586
3587 auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
3588 scrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
3589 scrolled->set_expand(true);
3590 scrolled->set_min_content_height(160);
3591 scrolled->set_child(*listView);
3592 innerPay->append(*scrolled);
3593
3594 auto reload_from_file = [store]() {
3595 store->remove_all();
3597 for (const auto& d : domains)
3598 store->append(Gtk::StringObject::create(d));
3599 };
3600 reload_from_file();
3601
3602 auto entry = Gtk::make_managed<Gtk::Entry>();
3603 entry->set_placeholder_text(_("Inserisci dominio o URL (es. paypal.com oppure https://checkout.stripe.com)"));
3604 entry->set_hexpand(true);
3605 entry->add_css_class("whitelist-entry");
3606
3607 auto btnAdd = Gtk::make_managed<Gtk::Button>(_("Aggiungi"));
3608 auto btnRemove = Gtk::make_managed<Gtk::Button>(_("Rimuovi selezionato"));
3609 auto btnSave = Gtk::make_managed<Gtk::Button>(_("Salva"));
3610 auto btnReload = Gtk::make_managed<Gtk::Button>(_("Ripristina"));
3611
3612 auto rowBtns = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
3613 rowBtns->append(*entry);
3614 rowBtns->append(*btnAdd);
3615 rowBtns->append(*btnRemove);
3616 rowBtns->append(*btnReload);
3617 rowBtns->append(*btnSave);
3618 innerPay->append(*rowBtns);
3619
3620 btnAdd->signal_clicked().connect([store, entry, show_alert]() {
3621 std::string in = entry->get_text();
3622 std::string dom = normalize_domain_or_url(in);
3623 if (dom.empty()) {
3624 auto dlg = Gtk::AlertDialog::create(_("Valore non valido"));
3625 dlg->set_detail(_("Inserisci un dominio o URL valido."));
3626 show_alert(dlg);
3627 return;
3628 }
3629
3630 for (guint i = 0; i < store->get_n_items(); ++i) {
3631 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(store->get_object(i));
3632 if (obj && obj->get_string() == dom) {
3633 entry->set_text("");
3634 return;
3635 }
3636 }
3637
3638 store->append(Gtk::StringObject::create(dom));
3639 entry->set_text("");
3640 });
3641
3642 btnRemove->signal_clicked().connect([selection, store]() {
3643 guint pos = selection->get_selected();
3644 if (pos != GTK_INVALID_LIST_POSITION)
3645 store->remove(pos);
3646 });
3647
3648 btnReload->signal_clicked().connect([reload_from_file]() {
3649 reload_from_file();
3650 });
3651
3652 btnSave->signal_clicked().connect([store, swPay, lblPayStatus, show_alert]() {
3653 std::vector<std::string> domains;
3654 domains.reserve(store->get_n_items());
3655
3656 for (guint i = 0; i < store->get_n_items(); ++i) {
3657 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(store->get_object(i));
3658 if (obj) domains.push_back(obj->get_string());
3659 }
3660
3661 const bool enabled_flag = swPay->get_active();
3662
3663 if (!save_payments_domains(domains, enabled_flag)) {
3664 auto dlg = Gtk::AlertDialog::create(_("Errore"));
3665 dlg->set_detail(_("Impossibile salvare payments.json."));
3666 show_alert(dlg);
3667 return;
3668 }
3669
3670 lblPayStatus->set_text(_("✔ Lista pagamenti salvata"));
3671 lblPayStatus->remove_css_class("status-muted");
3672 lblPayStatus->add_css_class("status-ok");
3673
3675 std::thread([]() {
3676 (bg_process::run({"/usr/libexec/bastionguard/bastionguard-service", "--user", "restart", "BastionGuard-cef.service"}).exit_code);
3677 }).detach();
3678 }
3679 });
3680
3681 swPay->property_active().signal_changed().connect([swPay, refreshPayStatus]() {
3682 const bool enabled = swPay->get_active();
3685 refreshPayStatus();
3686 });
3687
3688 auto btnInstallSafeNav = Gtk::make_managed<Gtk::Button>(_("Installazione navigazione sicura"));
3689 btnInstallSafeNav->add_css_class("btn-warning");
3690 innerPay->append(*btnInstallSafeNav);
3691
3692 auto installLogBuffer = Gtk::TextBuffer::create();
3693
3694 btnInstallSafeNav->signal_clicked().connect(
3695 [this, btnInstallSafeNav, installLogBuffer, lblPayStatus, run_cmd_capture, resolve_ca_path, show_alert]() {
3697 lblPayStatus->set_text(_("CEF e installazione CA non disponibili su questa build o distribuzione."));
3698 return;
3699 }
3700 btnInstallSafeNav->set_sensitive(false);
3701 installLogBuffer->set_text(_("Avvio installazione navigazione sicura...\n"));
3702
3703 Gtk::Window* log_popup = create_log_popup(this, installLogBuffer);
3704
3705 std::thread([this, alive = alive_, btnInstallSafeNav, installLogBuffer, lblPayStatus, run_cmd_capture, resolve_ca_path, show_alert, log_popup]() {
3706 std::string final_log;
3707 bool install_ok = false;
3708 bool restart_ok = false;
3709
3710 const std::string ca_src = resolve_ca_path();
3711 const std::string helper = "/usr/share/BastionGuard/data/scripts/install-ca-system.sh";
3712
3713 if (ca_src.empty()) {
3714 final_log += "[BastionGuard] CA non trovata nella home utente né in /etc.\n";
3715 } else if (!std::filesystem::exists(helper)) {
3716 final_log += std::string("[BastionGuard] Helper non trovato: ") + helper + "\n";
3717 } else {
3718 final_log += "[BastionGuard] Uso certificato: " + ca_src + "\n";
3719 final_log += "[BastionGuard] Eseguo install-ca-system.sh con pkexec...\n\n";
3720
3721 std::string out1, err1;
3722 install_ok = run_cmd_capture({"pkexec", helper, ca_src}, &out1, &err1);
3723
3724 if (!out1.empty()) final_log += out1;
3725 if (!err1.empty()) {
3726 if (!final_log.empty() && final_log.back() != '\n') final_log += "\n";
3727 final_log += err1;
3728 }
3729
3730 if (!install_ok) {
3731 final_log += "\n[BastionGuard] pkexec fallito, tentativo fallback con sudo --non-interactive...\n";
3732 std::string out2, err2;
3733 install_ok = run_cmd_capture({"sudo", "--non-interactive", helper, ca_src}, &out2, &err2);
3734
3735 if (!out2.empty()) final_log += out2;
3736 if (!err2.empty()) {
3737 if (!final_log.empty() && final_log.back() != '\n') final_log += "\n";
3738 final_log += err2;
3739 }
3740 }
3741
3742 if (install_ok) {
3743 final_log += "\n[BastionGuard] Installazione completata. Riavvio BastionGuard-cef.service (user)...\n";
3744 std::string out3, err3;
3745 restart_ok = run_cmd_capture(
3746 {"/usr/libexec/bastionguard/bastionguard-service", "--user", "restart", "BastionGuard-cef.service"},
3747 &out3, &err3
3748 );
3749
3750 if (!out3.empty()) final_log += out3;
3751 if (!err3.empty()) {
3752 if (!final_log.empty() && final_log.back() != '\n') final_log += "\n";
3753 final_log += err3;
3754 }
3755
3756 if (restart_ok)
3757 final_log += "\n[BastionGuard] ✅ BastionGuard-cef.service riavviato correttamente.\n";
3758 else
3759 final_log += "\n[BastionGuard] ⚠️ Impossibile riavviare BastionGuard-cef.service in modalità user.\n";
3760 } else {
3761 final_log += "\n[BastionGuard] ❌ Installazione navigazione sicura fallita.\n";
3762 }
3763 }
3764
3765 // Se la pagina è già stata distrutta, non schedulare la UI callback.
3766 if (!alive->load()) return;
3767
3768 Glib::MainContext::get_default()->invoke(
3769 [this, alive, btnInstallSafeNav, installLogBuffer, lblPayStatus, final_log, install_ok, restart_ok, show_alert, log_popup]() -> bool {
3770 if (!alive->load()) return false; // pagina morta
3771 installLogBuffer->set_text(final_log);
3772 btnInstallSafeNav->set_sensitive(true);
3773
3774 if (log_popup)
3775 log_popup->present();
3776
3777 if (install_ok) {
3778 lblPayStatus->set_text(_("✔ Navigazione sicura installata"));
3779 lblPayStatus->remove_css_class("status-muted");
3780 lblPayStatus->add_css_class("status-ok");
3781
3782 auto dlg = Gtk::AlertDialog::create(_("Installazione completata"));
3783 if (restart_ok) {
3784 dlg->set_detail(_("La navigazione sicura è stata installata correttamente.\n\nChiudi il browser e riaprilo."));
3785 } else {
3786 dlg->set_detail(_("La navigazione sicura è stata installata, ma il riavvio del servizio BastionGuard-cef non è riuscito.\n\nChiudi il browser e riaprilo."));
3787 }
3788 show_alert(dlg);
3789 } else {
3790 lblPayStatus->set_text(_("❌ Installazione navigazione sicura fallita"));
3791 lblPayStatus->remove_css_class("status-ok");
3792 lblPayStatus->add_css_class("status-muted");
3793
3794 auto dlg = Gtk::AlertDialog::create(_("Errore"));
3795 dlg->set_detail(_("Impossibile completare l'installazione della navigazione sicura. Controlla il log nella finestra aperta."));
3796 show_alert(dlg);
3797 }
3798
3799 return false;
3800 }
3801 );
3802 }).detach();
3803 }
3804 );
3805
3807
3808 if (!cef_available) {
3809 swPay->set_active(false);
3810 swPay->set_sensitive(false);
3811 entry->set_sensitive(false);
3812 btnAdd->set_sensitive(false);
3813 btnRemove->set_sensitive(false);
3814 btnReload->set_sensitive(false);
3815 btnSave->set_sensitive(false);
3816 btnInstallSafeNav->set_sensitive(false);
3819 lblPayStatus->set_text(_("⊘ CEF disabilitato su Fedora/RHEL/Alma/Rocky o escluso dalla build."));
3820 lblPayStatus->remove_css_class("status-ok");
3821 lblPayStatus->add_css_class("status-muted");
3822 }
3823
3824 framePay->set_child(*innerPay);
3825 page_pay->append(*framePay);
3826
3827 page_order_.push_back(page_pay);
3828 stack.add(*page_pay, "secure-payments", _("Pagamenti Sicuri"));
3829}
static void set_secure_payments_enabled(bool enabled)
static bool get_secure_payments_enabled()
static bool update_payments_enabled_only(bool enabled_flag)
static std::vector< std::string > load_payments_domains()
static void ensure_payments_json_exists()
static std::string normalize_domain_or_url(const std::string &in_raw)
static Gtk::Window * create_log_popup(Gtk::Widget *owner, const Glib::RefPtr< Gtk::TextBuffer > &buffer)
static bool save_payments_domains(const std::vector< std::string > &domains_in, bool enabled_flag)

References _, alive_, BastionGuard::Platform::cef_available(), create_log_popup(), ensure_payments_json_exists(), SettingsStore::get_secure_payments_enabled(), load_payments_domains(), normalize_domain_or_url(), page_order_, bg_process::run(), save_payments_domains(), SettingsStore::set_secure_payments_enabled(), stack, and update_payments_enabled_only().

Referenced by SettingsPage().

◆ build_services_section()

void SettingsPage::build_services_section ( Gtk::Box & parent,
const std::vector< std::tuple< std::string, Glib::ustring, Glib::ustring > > & services,
bool system_units )
private

Definition at line 4281 of file SettingsPage.cpp.

4285{
4286 auto grid = Gtk::make_managed<Gtk::Grid>();
4287 grid->set_column_spacing(28);
4288 grid->set_row_spacing(18);
4289 grid->set_margin_top(12);
4290 grid->set_margin_start(8);
4291 grid->set_margin_end(8);
4292
4293 struct RowBinding {
4294 Gtk::Switch* sw;
4295 std::string name;
4296 };
4297 auto bindings = std::make_shared<std::vector<RowBinding>>();
4298 bindings->reserve(services.size());
4299
4300 int col = 0;
4301 int row = 0;
4302
4303 for (const auto& svc : services)
4304 {
4305 const std::string name = std::get<0>(svc);
4306 const Glib::ustring label = std::get<1>(svc);
4307 const Glib::ustring description = std::get<2>(svc);
4308
4309 auto service_box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 4);
4310 service_box->set_hexpand(true);
4311
4312 auto lbl_name = Gtk::make_managed<Gtk::Label>(label);
4313 lbl_name->set_halign(Gtk::Align::START);
4314 lbl_name->add_css_class("service-name");
4315
4316 auto lbl_desc = Gtk::make_managed<Gtk::Label>(description);
4317 lbl_desc->set_halign(Gtk::Align::START);
4318 lbl_desc->set_wrap(true);
4319 lbl_desc->set_wrap_mode(Pango::WrapMode::WORD_CHAR);
4320 lbl_desc->set_ellipsize(Pango::EllipsizeMode::END);
4321 lbl_desc->set_max_width_chars(42);
4322 lbl_desc->set_hexpand(true);
4323 lbl_desc->add_css_class("service-desc");
4324
4325 service_box->append(*lbl_name);
4326 service_box->append(*lbl_desc);
4327
4328 auto sw = Gtk::make_managed<Gtk::Switch>();
4329 sw->set_halign(Gtk::Align::END);
4330 sw->set_valign(Gtk::Align::CENTER);
4331 sw->set_hexpand(false);
4332
4333 bool enabled = system_units ? is_system_service_enabled(name)
4335 sw->set_active(enabled);
4336
4337 auto row_container = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 16);
4338 row_container->set_hexpand(true);
4339 row_container->add_css_class("service-row");
4340 row_container->append(*service_box);
4341 row_container->append(*sw);
4342
4343 grid->attach(*row_container, col, row, 1, 1);
4344
4345 bindings->push_back({sw, name});
4346
4347 // Cambio stato
4348 sw->property_active().signal_changed().connect(
4349 [this, name, sw, system_units]()
4350 {
4351 bool want_enabled = sw->get_active();
4352
4353 bool success = false;
4354 if (system_units)
4355 success = want_enabled ? enable_system_service(name) : disable_system_service(name);
4356 else
4357 success = want_enabled ? enable_user_service(name) : disable_user_service(name);
4358
4359 if (!success)
4360 {
4361 sw->set_active(!want_enabled);
4362
4364 want_enabled ? _("Impossibile abilitare il servizio")
4365 : _("Impossibile disabilitare il servizio"),
4366 name
4367 );
4368 }
4369 });
4370
4371 col++;
4372 if (col >= 2)
4373 {
4374 col = 0;
4375 row++;
4376 }
4377 }
4378
4379 parent.append(*grid);
4380
4381 auto btn_refresh = Gtk::make_managed<Gtk::Button>(_("Aggiorna stato servizi"));
4382 btn_refresh->set_halign(Gtk::Align::END);
4383 btn_refresh->signal_clicked().connect(
4384 [this, bindings, system_units]()
4385 {
4386 for (auto& b : *bindings)
4387 {
4388 bool enabled = system_units ? is_system_service_enabled(b.name)
4389 : is_user_service_enabled(b.name);
4390 b.sw->set_active(enabled);
4391 }
4392 });
4393
4394 parent.append(*btn_refresh);
4395}
bool enable_system_service(const std::string &unit_name)
static void show_service_error_dialog(const Glib::ustring &message, const std::string &service_name)
bool enable_user_service(const std::string &service_name)
bool is_user_service_enabled(const std::string &service_name)
bool is_system_service_enabled(const std::string &unit_name)
bool disable_user_service(const std::string &service_name)
bool disable_system_service(const std::string &unit_name)

References _, disable_system_service(), disable_user_service(), enable_system_service(), enable_user_service(), is_system_service_enabled(), is_user_service_enabled(), and show_service_error_dialog().

Referenced by build_system_services_tab(), and build_user_services_tab().

◆ build_system_services_tab()

void SettingsPage::build_system_services_tab ( )
private

Definition at line 4235 of file SettingsPage.cpp.

4236{
4237 auto page = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
4238 page->set_margin(12);
4239
4240 auto frame = Gtk::make_managed<Gtk::Frame>();
4241 auto inner = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
4242 inner->set_margin(10);
4243
4244 auto title = Gtk::make_managed<Gtk::Label>(_("Servizi di Sistema (pkexec)"));
4245 title->set_halign(Gtk::Align::START);
4246 title->add_css_class("card-title");
4247 inner->append(*title);
4248
4249 auto desc = Gtk::make_managed<Gtk::Label>(
4250 _("Questi servizi richiedono privilegi amministrativi.\n"
4251 "Vengono gestiti con: pkexec /usr/libexec/bastionguard/bastionguard-service --system ...")
4252 );
4253 desc->set_wrap(true);
4254 desc->set_halign(Gtk::Align::START);
4255 desc->add_css_class("card-description");
4256 inner->append(*desc);
4257
4258 auto warn = Gtk::make_managed<Gtk::Label>(
4259 _("Durante l’attivazione/disattivazione potrebbe essere richiesta la password.")
4260 );
4261 warn->set_wrap(true);
4262 warn->add_css_class("alert-warning");
4263 inner->append(*warn);
4264
4265 const std::vector<std::tuple<std::string, Glib::ustring, Glib::ustring>> system_services = {
4266 {"BastionGuard-phishing-scanner.service", _("Phishing Scanner (System)"), _("Scansione anti-phishing a livello di sistema")},
4267 {"BastionGuard-ransomware-realtime.service", _("Ransomware Realtime (System)"), _("Monitor realtime ransomware a livello di sistema")},
4268 {"BastionGuard-usbd.service", _("USB Protection (System)"), _("Monitoraggio e blocco dispositivi USB sospetti")},
4269 };
4270
4271 build_services_section(*inner, system_services, true);
4272
4273 frame->set_child(*inner);
4274 page->append(*frame);
4275
4276 page_order_.push_back(page);
4277 stack.add(*page, "system-services", _("Servizi Sistema"));
4278}
void build_services_section(Gtk::Box &parent, const std::vector< std::tuple< std::string, Glib::ustring, Glib::ustring > > &services, bool system_units)

References _, build_services_section(), page_order_, and stack.

Referenced by SettingsPage().

◆ build_user_services_tab()

void SettingsPage::build_user_services_tab ( )
private

Definition at line 4178 of file SettingsPage.cpp.

4179{
4180 auto page = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
4181 page->set_margin(12);
4182
4183 auto frame = Gtk::make_managed<Gtk::Frame>();
4184 auto inner = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 10);
4185 inner->set_margin(10);
4186
4187 auto title = Gtk::make_managed<Gtk::Label>(_("Servizi utente"));
4188 title->set_halign(Gtk::Align::START);
4189 title->add_css_class("card-title");
4190 inner->append(*title);
4191
4192 auto desc = Gtk::make_managed<Gtk::Label>(
4193 _("Questi servizi vengono gestiti dal backend init rilevato.\n"
4194 "Abilitare = avvio automatico al login. Disabilitare = non parte automaticamente.")
4195 );
4196 desc->set_wrap(true);
4197 desc->set_halign(Gtk::Align::START);
4198 desc->add_css_class("card-description");
4199 inner->append(*desc);
4200
4201 auto info = Gtk::make_managed<Gtk::Label>(
4202 _("Nota: puoi avviarli manualmente con: /usr/libexec/bastionguard/bastionguard-service --user start <unit>")
4203 );
4204 info->set_wrap(true);
4205 info->add_css_class("alert-info");
4206 inner->append(*info);
4207
4208 std::vector<std::tuple<std::string, Glib::ustring, Glib::ustring>> user_services = {
4209 {"BastionGuard-privacyd.service", _("Privacy Guard"), _("Blocco microfono e webcam quando non in uso")},
4210 {"BastionGuard-ransomware-alert.service", _("Ransomware Alert"), _("Notifiche su possibili attività ransomware")},
4211 {"BastionGuard-ransomware-realtime-alert.service", _("Ransomware Realtime Alert"), _("Avvisi in tempo reale su comportamenti sospetti")},
4212 {"BastionGuard-ransomware-scanner.service", _("Ransomware Scanner"), _("Scansione periodica alla ricerca di comportamenti malevoli")},
4213 {"BastionGuard-useragent.service", _("User-Agent Randomizer"), _("Modifica user-agent per aumentare anonimato")},
4214 {"BastionGuard-pacd.service", _("PAC Daemon"), _("Gestione automatica di proxy PAC sicuri")},
4215 {"BastionGuard-mailproxy.service", _("Mail Proxy"), _("Proxy SMTP locale per protezione email in uscita")}
4216 };
4217
4219 user_services.emplace_back(
4220 "BastionGuard-cef.service",
4221 _("CEF Sandbox Service"),
4222 _("Supporto in background per pagamenti sicuri con CEF")
4223 );
4224 }
4225
4226 build_services_section(*inner, user_services, false);
4227
4228 frame->set_child(*inner);
4229 page->append(*frame);
4230
4231 page_order_.push_back(page);
4232 stack.add(*page, "user-services", _("Servizi Utente"));
4233}

References _, build_services_section(), BastionGuard::Platform::cef_available(), page_order_, and stack.

Referenced by SettingsPage().

◆ build_whitelist_tab()

void SettingsPage::build_whitelist_tab ( )
private

Definition at line 2932 of file SettingsPage.cpp.

2932 {
2933 auto page = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 12);
2934
2935 auto lblTitle = Gtk::make_managed<Gtk::Label>(_("Gestione Whitelist / Blacklist Anti-Phishing"));
2936 lblTitle->set_halign(Gtk::Align::START);
2937 lblTitle->set_margin_bottom(6);
2938 page->append(*lblTitle);
2939
2940
2941 const std::string baseDir = Glib::get_home_dir() + "/.local/share/BastionGuard/phishing";
2942 std::filesystem::create_directories(baseDir);
2943
2944 const std::string wlUserPath = baseDir + "/whitelist.txt";
2945 const std::string wlSysPath = "/usr/share/BastionGuard/data/phishing/whitelist.txt";
2946
2947 const std::string blUserPath = baseDir + "/blacklist_custom.txt";
2948 const std::string blSysPath = "/usr/share/BastionGuard/data/phishing/blacklist_custom.txt";
2949
2950 const std::string dnsmasqConfPath = "/etc/dnsmasq.d/bastionguard-blacklist.conf";
2951 const std::string tmpDnsmasqConf = "/tmp/bastionguard-blacklist.conf";
2952
2953
2954 auto searchEntry = Gtk::make_managed<Gtk::SearchEntry>();
2955 searchEntry->set_placeholder_text(_("Cerca in whitelist/blacklist..."));
2956 page->append(*searchEntry);
2957
2958
2959 auto wlStoreView = Gio::ListStore<Gtk::StringObject>::create();
2960 auto blStoreView = Gio::ListStore<Gtk::StringObject>::create();
2961
2962
2963 auto wlSelection = Gtk::SingleSelection::create(wlStoreView);
2964 auto blSelection = Gtk::SingleSelection::create(blStoreView);
2965
2966
2967 auto factory = Gtk::SignalListItemFactory::create();
2968 factory->signal_setup().connect([](const Glib::RefPtr<Gtk::ListItem>& item) {
2969 auto lbl = Gtk::make_managed<Gtk::Label>();
2970 lbl->set_xalign(0);
2971 lbl->set_margin(4);
2972 item->set_child(*lbl);
2973 });
2974 factory->signal_bind().connect([](const Glib::RefPtr<Gtk::ListItem>& item) {
2975 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(item->get_item());
2976 if (auto lbl = dynamic_cast<Gtk::Label*>(item->get_child()))
2977 lbl->set_text(obj ? obj->get_string() : "");
2978 });
2979
2980
2981 auto wlLabel = Gtk::make_managed<Gtk::Label>(_("Whitelist (consenti)"));
2982 wlLabel->set_halign(Gtk::Align::START);
2983 page->append(*wlLabel);
2984
2985 Gtk::ListView wlListView(wlSelection, factory);
2986 wlListView.set_vexpand(true);
2987 wlListView.add_css_class("whitelist-view");
2988
2989 auto wlScrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
2990 wlScrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
2991 wlScrolled->set_expand(true);
2992 wlScrolled->set_child(wlListView);
2993 page->append(*wlScrolled);
2994
2995 auto wlEntry = Gtk::make_managed<Gtk::Entry>();
2996 wlEntry->set_placeholder_text(_("Aggiungi a whitelist (dominio o IPv4)"));
2997 wlEntry->set_hexpand(true);
2998
2999 auto wlAdd = Gtk::make_managed<Gtk::Button>(_("Aggiungi"));
3000 auto wlRemove = Gtk::make_managed<Gtk::Button>(_("Rimuovi selezionato"));
3001
3002 auto wlRow = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
3003 wlRow->append(*wlEntry);
3004 wlRow->append(*wlAdd);
3005 wlRow->append(*wlRemove);
3006 page->append(*wlRow);
3007
3008
3009 auto blLabel = Gtk::make_managed<Gtk::Label>(_("Blacklist custom (blocca via dnsmasq)"));
3010 blLabel->set_halign(Gtk::Align::START);
3011 blLabel->set_margin_top(8);
3012 page->append(*blLabel);
3013
3014 Gtk::ListView blListView(blSelection, factory);
3015 blListView.set_vexpand(true);
3016 blListView.add_css_class("whitelist-view");
3017
3018 auto blScrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
3019 blScrolled->set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
3020 blScrolled->set_expand(true);
3021 blScrolled->set_child(blListView);
3022 page->append(*blScrolled);
3023
3024 auto blEntry = Gtk::make_managed<Gtk::Entry>();
3025 blEntry->set_placeholder_text(_("Aggiungi a blacklist (dominio o IPv4)"));
3026 blEntry->set_hexpand(true);
3027
3028 auto blAdd = Gtk::make_managed<Gtk::Button>(_("Aggiungi"));
3029 auto blRemove = Gtk::make_managed<Gtk::Button>(_("Rimuovi selezionato"));
3030
3031 auto blRow = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
3032 blRow->append(*blEntry);
3033 blRow->append(*blAdd);
3034 blRow->append(*blRemove);
3035 page->append(*blRow);
3036
3037
3038 auto btnReload = Gtk::make_managed<Gtk::Button>(_("Ricarica"));
3039 auto btnSave = Gtk::make_managed<Gtk::Button>(_("Salva modifiche"));
3040
3041 auto bottom = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);
3042 bottom->append(*btnReload);
3043 bottom->append(*btnSave);
3044 page->append(*bottom);
3045
3046
3047 auto wlAll = std::make_shared<std::vector<std::string>>();
3048 auto blAll = std::make_shared<std::vector<std::string>>();
3049
3050 // Utils
3051 auto trim = [](std::string s) {
3052 auto notSpace = [](unsigned char c){ return !std::isspace(c); };
3053 s.erase(s.begin(), std::find_if(s.begin(), s.end(), notSpace));
3054 s.erase(std::find_if(s.rbegin(), s.rend(), notSpace).base(), s.end());
3055 return s;
3056 };
3057 auto toLower = [](std::string s) {
3058 std::transform(s.begin(), s.end(), s.begin(),
3059 [](unsigned char c){ return (unsigned char)std::tolower(c); });
3060 return s;
3061 };
3062 auto isIPv4 = [](const std::string& s) -> bool {
3063 static const std::regex re(
3064 R"(^(25[0-5]|2[0-4]\d|1?\d?\d)(\.(25[0-5]|2[0-4]\d|1?\d?\d)){3}$)"
3065 );
3066 return std::regex_match(s, re);
3067 };
3068 auto isDomain = [](const std::string& s) -> bool {
3069 static const std::regex re(
3070 R"(^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$)",
3071 std::regex::icase
3072 );
3073 if (!std::regex_match(s, re)) return false;
3074 if (s.find("..") != std::string::npos) return false;
3075 return true;
3076 };
3077
3078 auto loadFileToVector = [](const std::string& userPath,
3079 const std::string& sysPath,
3080 std::vector<std::string>& out) {
3081 out.clear();
3082
3083 auto load = [&](const std::string& path) -> bool {
3084 std::ifstream f(path);
3085 if (!f.is_open()) return false;
3086 std::string line;
3087 while (std::getline(f, line)) {
3088 if (!line.empty()) out.push_back(line);
3089 }
3090 return true;
3091 };
3092
3093 if (!load(userPath)) load(sysPath);
3094
3095
3096 std::vector<std::string> dedup;
3097 dedup.reserve(out.size());
3098 for (auto& s : out) {
3099 if (std::find(dedup.begin(), dedup.end(), s) == dedup.end())
3100 dedup.push_back(s);
3101 }
3102 out.swap(dedup);
3103 };
3104
3105 auto applyFilter = [=]() {
3106 const std::string qraw = Glib::ustring(searchEntry->get_text()).raw();
3107 const Glib::ustring q = Glib::ustring(qraw).lowercase();
3108
3109 wlStoreView->remove_all();
3110 for (const auto& s : *wlAll) {
3111 if (q.empty() || Glib::ustring(s).lowercase().find(q) != Glib::ustring::npos)
3112 wlStoreView->append(Gtk::StringObject::create(s));
3113 }
3114
3115 blStoreView->remove_all();
3116 for (const auto& s : *blAll) {
3117 if (q.empty() || Glib::ustring(s).lowercase().find(q) != Glib::ustring::npos)
3118 blStoreView->append(Gtk::StringObject::create(s));
3119 }
3120 };
3121
3122 auto loadAll = [=]() {
3123 loadFileToVector(wlUserPath, wlSysPath, *wlAll);
3124 loadFileToVector(blUserPath, blSysPath, *blAll);
3125 applyFilter();
3126 };
3127
3128 auto existsInVec = [](const std::vector<std::string>& v, const std::string& x) -> bool {
3129 return std::find(v.begin(), v.end(), x) != v.end();
3130 };
3131
3132 auto removeFromVec = [](std::vector<std::string>& v, const std::string& x) {
3133 v.erase(std::remove(v.begin(), v.end(), x), v.end());
3134 };
3135
3136
3137 loadAll();
3138
3139
3140 searchEntry->signal_search_changed().connect([applyFilter]() {
3141 applyFilter();
3142 });
3143
3144
3145 wlAdd->signal_clicked().connect([=]() {
3146 std::string v = trim(wlEntry->get_text());
3147 if (v.empty()) return;
3148
3149 std::string norm = isIPv4(v) ? v : toLower(v);
3150 if (!isIPv4(norm) && !isDomain(norm)) {
3151 auto dlg = Gtk::AlertDialog::create(_("Valore non valido"));
3152 dlg->set_detail(_("Inserisci un dominio valido o un IPv4 valido."));
3153 dlg->show();
3154 return;
3155 }
3156 if (existsInVec(*wlAll, norm)) {
3157 auto dlg = Gtk::AlertDialog::create(_("Già presente"));
3158 dlg->set_detail(_("Questo elemento è già nella whitelist."));
3159 dlg->show();
3160 wlEntry->set_text("");
3161 return;
3162 }
3163
3164 wlAll->push_back(norm);
3165 wlEntry->set_text("");
3166 applyFilter();
3167 });
3168
3169
3170 wlRemove->signal_clicked().connect([=]() {
3171 guint pos = wlSelection->get_selected();
3172 if (pos == GTK_INVALID_LIST_POSITION) return;
3173
3174 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(wlStoreView->get_object(pos));
3175 if (!obj) return;
3176
3177 removeFromVec(*wlAll, obj->get_string());
3178 applyFilter();
3179 });
3180
3181
3182 blAdd->signal_clicked().connect([=]() {
3183 std::string v = trim(blEntry->get_text());
3184 if (v.empty()) return;
3185
3186 std::string norm = isIPv4(v) ? v : toLower(v);
3187 if (!isIPv4(norm) && !isDomain(norm)) {
3188 auto dlg = Gtk::AlertDialog::create(_("Valore non valido"));
3189 dlg->set_detail(_("Inserisci un dominio valido o un IPv4 valido."));
3190 dlg->show();
3191 return;
3192 }
3193 if (existsInVec(*blAll, norm)) {
3194 auto dlg = Gtk::AlertDialog::create(_("Già presente"));
3195 dlg->set_detail(_("Questo elemento è già nella blacklist."));
3196 dlg->show();
3197 blEntry->set_text("");
3198 return;
3199 }
3200
3201 blAll->push_back(norm);
3202 blEntry->set_text("");
3203 applyFilter();
3204 });
3205
3206
3207 blRemove->signal_clicked().connect([=]() {
3208 guint pos = blSelection->get_selected();
3209 if (pos == GTK_INVALID_LIST_POSITION) return;
3210
3211 auto obj = std::dynamic_pointer_cast<Gtk::StringObject>(blStoreView->get_object(pos));
3212 if (!obj) return;
3213
3214 removeFromVec(*blAll, obj->get_string());
3215 applyFilter();
3216 });
3217
3218
3219 btnReload->signal_clicked().connect([=]() { loadAll(); });
3220
3221
3222 btnSave->signal_clicked().connect([=]() {
3223
3224 {
3225 std::ofstream f(wlUserPath, std::ios::trunc);
3226 if (!f.is_open()) {
3227 auto dlg = Gtk::AlertDialog::create(_("Errore"));
3228 dlg->set_detail(_("Impossibile salvare la whitelist utente."));
3229 dlg->show();
3230 return;
3231 }
3232 for (const auto& s : *wlAll) f << s << "\n";
3233 }
3234
3235 {
3236 std::ofstream f(blUserPath, std::ios::trunc);
3237 if (!f.is_open()) {
3238 auto dlg = Gtk::AlertDialog::create(_("Errore"));
3239 dlg->set_detail(_("Impossibile salvare la blacklist utente."));
3240 dlg->show();
3241 return;
3242 }
3243 for (const auto& s : *blAll) f << s << "\n";
3244 }
3245
3246 {
3247 std::ofstream f(tmpDnsmasqConf, std::ios::trunc);
3248 if (!f.is_open()) {
3249 auto dlg = Gtk::AlertDialog::create(_("Errore"));
3250 dlg->set_detail(_("Impossibile creare file temporaneo per dnsmasq."));
3251 dlg->show();
3252 return;
3253 }
3254
3255 f << "# Generated by BastionGuard\n";
3256 for (const auto& item : *blAll) {
3257 if (!isIPv4(item)) {
3258 f << "address=/" << item << "/127.0.0.2\n";
3259 } else {
3260 f << "# IP entry (not used by dnsmasq address=): " << item << "\n";
3261 }
3262 }
3263 }
3264
3265 const bool saved =
3266 bg_process::run({"pkexec", "/usr/bin/install", "-D", "-m", "0644", wlUserPath, wlSysPath}).ok() &&
3267 bg_process::run({"pkexec", "/usr/bin/install", "-D", "-m", "0644", blUserPath, blSysPath}).ok() &&
3268 bg_process::run({"pkexec", "/usr/bin/install", "-D", "-m", "0644", tmpDnsmasqConf, dnsmasqConfPath}).ok() &&
3269 bg_process::run({"pkexec", "/usr/libexec/bastionguard/bastionguard-service",
3270 "--system", "reload", "dnsmasq.service"}).ok();
3271 if (!saved) {
3272 auto dlg = Gtk::AlertDialog::create(_("Errore"));
3273 dlg->set_detail(_("Impossibile installare i file o ricaricare dnsmasq."));
3274 dlg->show();
3275 return;
3276 }
3277
3278 auto dlg = Gtk::AlertDialog::create(_("Salvataggio completato"));
3279 dlg->set_detail(_("Whitelist/Blacklist salvate. Config dnsmasq aggiornata (127.0.0.2) e servizio ricaricato."));
3280 dlg->show();
3281
3282 std::thread([=]() {
3285 (bg_process::run({"/usr/libexec/bastionguard/bastionguard-service", "--user", "restart", "BastionGuard-cef"}).exit_code);
3286 }
3287 }).detach();
3288 });
3289
3290 page_order_.push_back(page);
3291 stack.add(*page, "advanced-anti-phishing", _("Anti-Phishing avanzate"));
3292}
void dedup(std::vector< ProxyEndpoint > &v)

References _, BastionGuard::Platform::cef_available(), Backend::instance(), page_order_, bg_process::run(), stack, and Backend::updatePhishLists().

Referenced by SettingsPage().

◆ buildUi()

void SettingsPage::buildUi ( )
private

Definition at line 63 of file SettingsPage.cpp.

64{
65 set_hexpand(true);
66 set_vexpand(true);
67
68 m_scroll.set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC);
69 m_scroll.set_hexpand(true);
70 m_scroll.set_vexpand(true);
71
72 m_content.set_margin_top(24);
73 m_content.set_margin_bottom(24);
74 m_content.set_margin_start(24);
75 m_content.set_margin_end(24);
76 m_content.set_hexpand(true);
77 m_content.set_spacing(16);
78
79 m_title.set_markup(
80 "<span size='xx-large' weight='bold'>" +
81 Glib::Markup::escape_text(_("Impostazioni")) +
82 "</span>");
83 m_title.set_halign(Gtk::Align::START);
84
85 m_intro.set_text(_("Da questa pagina puoi attivare o disattivare BastionGuard™ Secure Connection in modo persistente. La scelta viene salvata in ~/.config; quando disattivi viene fermato/disabilitato bsc-daemon, l'autostart viene rimosso da /etc/xdg/autostart dopo backup nello stesso percorso e i flag vengono impostati a false."));
86 m_intro.add_css_class("alert-info");
87 m_intro.set_wrap(true);
88 m_intro.set_halign(Gtk::Align::START);
89 m_intro.set_justify(Gtk::Justification::LEFT);
90 m_intro.set_margin_bottom(4);
91
92 // =========================
93 // Card: Protezione di sistema
94 // =========================
95 m_serviceFrame.set_label(_("Protezione di sistema"));
97
98 m_serviceBox.set_margin_top(12);
99 m_serviceBox.set_margin_bottom(12);
100 m_serviceBox.set_margin_start(12);
101 m_serviceBox.set_margin_end(12);
102 m_serviceBox.set_spacing(12);
103 m_serviceBox.add_css_class("settings-card");
104
105 auto serviceHeader = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 12);
106 serviceHeader->set_hexpand(true);
107 serviceHeader->set_halign(Gtk::Align::FILL);
108
109 m_serviceTitle.set_text(_("Protezione di sistema"));
110 m_serviceTitle.set_halign(Gtk::Align::START);
111 m_serviceTitle.set_hexpand(true);
112 m_serviceTitle.add_css_class("settings-card-title");
113
114 m_serviceBadge.set_halign(Gtk::Align::END);
115 m_serviceBadge.set_valign(Gtk::Align::CENTER);
116
117 serviceHeader->append(m_serviceTitle);
118 serviceHeader->append(m_serviceBadge);
119
120 auto switchRow = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 12);
121 switchRow->set_halign(Gtk::Align::FILL);
122 switchRow->set_hexpand(true);
123
124 m_enableLabel.set_text(_("BastionGuard™ Secure Connection attivo"));
125 m_enableLabel.set_halign(Gtk::Align::START);
126 m_enableLabel.set_hexpand(true);
127 m_enableLabel.set_valign(Gtk::Align::CENTER);
128
129 // Il CSS dell'app usa un reset globale (`all: unset`), quindi i widget
130 // nativi come Gtk::Switch devono avere dimensioni/stile espliciti.
131 // Senza questo il controllo può essere presente nel layout ma invisibile.
132 m_enableSwitch.set_halign(Gtk::Align::END);
133 m_enableSwitch.set_valign(Gtk::Align::CENTER);
134 m_enableSwitch.set_size_request(56, 30);
135 m_enableSwitch.add_css_class("bsc-toggle-switch");
136 m_enableSwitch.set_tooltip_text(_("Attiva o disattiva l'avvio automatico e bsc-daemon"));
137
138 switchRow->append(m_enableLabel);
139 switchRow->append(m_enableSwitch);
140
141 m_statusLabel.set_wrap(true);
142 m_statusLabel.set_halign(Gtk::Align::START);
143 m_statusLabel.set_xalign(0.0f);
144 m_statusLabel.set_selectable(true);
145
146 m_infoLabel.set_wrap(true);
147 m_infoLabel.set_halign(Gtk::Align::START);
148 m_infoLabel.set_xalign(0.0f);
149 m_infoLabel.set_text(_("Disattivando vengono eseguite queste operazioni: salvataggio di enabled=false, autostart_enabled=false e daemon_enabled=false, backup dell'autostart in /etc/xdg/autostart/bastionguard-sc-autostart.desktop.bak, rimozione dell'autostart attivo e disattivazione di bsc-daemon tramite il gestore servizi. Riattivando, il backup viene ripristinato e il servizio viene riabilitato."));
150 m_infoLabel.add_css_class("alert-info");
151
152 auto buttons = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
153 buttons->append(m_applyButton);
154 buttons->append(m_refreshButton);
155
156 m_serviceBox.append(*serviceHeader);
157 m_serviceBox.append(*switchRow);
160 m_serviceBox.append(*buttons);
161
162 // =========================
163 // Card: Stato rilevato
164 // =========================
165 m_detailsFrame.set_label(_("Stato rilevato"));
166 m_detailsFrame.set_child(m_detailsBox);
167
168 m_detailsBox.set_margin_top(12);
169 m_detailsBox.set_margin_bottom(12);
170 m_detailsBox.set_margin_start(12);
171 m_detailsBox.set_margin_end(12);
172 m_detailsBox.set_spacing(8);
173 m_detailsBox.add_css_class("settings-card");
174
175 auto detailsHeader = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 12);
176 detailsHeader->set_hexpand(true);
177 detailsHeader->set_halign(Gtk::Align::FILL);
178
179 m_detailsTitle.set_text(_("Stato rilevato"));
180 m_detailsTitle.set_halign(Gtk::Align::START);
181 m_detailsTitle.set_hexpand(true);
182 m_detailsTitle.add_css_class("settings-card-title");
183
184 m_detailsBadge.set_halign(Gtk::Align::END);
185 m_detailsBadge.set_valign(Gtk::Align::CENTER);
186
187 detailsHeader->append(m_detailsTitle);
188 detailsHeader->append(m_detailsBadge);
189
190 m_savedPrefLabel.set_halign(Gtk::Align::START);
191 m_savedPrefLabel.set_xalign(0.0f);
192
193 m_serviceStateLabel.set_halign(Gtk::Align::START);
194 m_serviceStateLabel.set_xalign(0.0f);
195
196 m_autostartStateLabel.set_halign(Gtk::Align::START);
197 m_autostartStateLabel.set_xalign(0.0f);
198
199 m_backupStateLabel.set_halign(Gtk::Align::START);
200 m_backupStateLabel.set_xalign(0.0f);
201
202 m_detailsBox.append(*detailsHeader);
207
208 m_enableSwitch.property_active().signal_changed().connect([this]() {
209 if (m_updatingSwitch) return;
210
211 const bool enabled = m_enableSwitch.get_active();
212 m_statusLabel.set_text(enabled
213 ? _("Attivazione richiesta dalle impostazioni...")
214 : _("Disattivazione richiesta dalle impostazioni..."));
216 });
217
218 m_applyButton.signal_clicked().connect([this]() {
219 const bool enabled = m_enableSwitch.get_active();
220 m_statusLabel.set_text(enabled
221 ? _("Attivazione richiesta dalle impostazioni...")
222 : _("Disattivazione richiesta dalle impostazioni..."));
224 });
225
226 m_refreshButton.signal_clicked().connect([this]() {
227 refreshState();
228 });
229
230 m_content.append(m_title);
231 m_content.append(m_intro);
234
235 m_scroll.set_child(m_content);
236 append(m_scroll);
237}
Gtk::Label m_serviceTitle
Gtk::Box m_detailsBox
Gtk::ScrolledWindow m_scroll
Gtk::Label m_savedPrefLabel
Gtk::Switch m_enableSwitch
Gtk::Box m_content
Gtk::Label m_intro
Gtk::Label m_autostartStateLabel
Gtk::Label m_infoLabel
Gtk::Frame m_detailsFrame
Gtk::Label m_serviceBadge
Gtk::Label m_title
Gtk::Label m_backupStateLabel
Gtk::Label m_serviceStateLabel
Gtk::Label m_statusLabel
Gtk::Frame m_serviceFrame
Gtk::Box m_serviceBox
Gtk::Label m_detailsBadge
sigc::signal< void(bool)> m_signalToggleProtectionRequested
Gtk::Label m_enableLabel
Gtk::Label m_detailsTitle

References _, m_applyButton, m_autostartStateLabel, m_backupStateLabel, m_content, m_detailsBadge, m_detailsBox, m_detailsFrame, m_detailsTitle, m_enableLabel, m_enableSwitch, m_infoLabel, m_intro, m_refreshButton, m_savedPrefLabel, m_scroll, m_serviceBadge, m_serviceBox, m_serviceFrame, m_serviceStateLabel, m_serviceTitle, m_signalToggleProtectionRequested, m_statusLabel, m_title, m_updatingSwitch, and refreshState().

Referenced by SettingsPage().

◆ collect_samba_dirs()

std::vector< std::string > SettingsPage::collect_samba_dirs ( const Glib::RefPtr< Gtk::ListStore > & store,
const SambaColumns & cols )
private

◆ disable_system_service()

bool SettingsPage::disable_system_service ( const std::string & unit_name)
private

Definition at line 4494 of file SettingsPage.cpp.

4495{
4496 pkexec_servicectl({"stop", unit_name}, nullptr);
4497 return pkexec_servicectl({"disable", "--now", unit_name}, nullptr);
4498}
bool pkexec_servicectl(const std::vector< std::string > &args, std::string *out_stdout=nullptr)

References pkexec_servicectl().

Referenced by build_services_section().

◆ disable_user_service()

bool SettingsPage::disable_user_service ( const std::string & service_name)
private

Definition at line 4450 of file SettingsPage.cpp.

4451{
4452 run_cmd({"/usr/libexec/bastionguard/bastionguard-service", "--user", "stop", service_name});
4453 return run_cmd({"/usr/libexec/bastionguard/bastionguard-service", "--user", "disable", "--now", service_name});
4454}
bool run_cmd(const std::vector< std::string > &argv, std::string *out_stdout=nullptr, bool silence_stderr=true)

References run_cmd().

Referenced by build_services_section().

◆ enable_system_service()

bool SettingsPage::enable_system_service ( const std::string & unit_name)
private

Definition at line 4485 of file SettingsPage.cpp.

4486{
4487 if (!pkexec_servicectl({"enable", "--now", unit_name}, nullptr))
4488 return false;
4489
4490 pkexec_servicectl({"start", unit_name}, nullptr);
4491 return true;
4492}

References pkexec_servicectl().

Referenced by build_services_section().

◆ enable_user_service()

bool SettingsPage::enable_user_service ( const std::string & service_name)
private

Definition at line 4441 of file SettingsPage.cpp.

4442{
4443 if (!run_cmd({"/usr/libexec/bastionguard/bastionguard-service", "--user", "enable", "--now", service_name}))
4444 return false;
4445
4446 run_cmd({"/usr/libexec/bastionguard/bastionguard-service", "--user", "start", service_name});
4447 return true;
4448}

References run_cmd().

Referenced by build_services_section().

◆ goto_page()

void SettingsPage::goto_page ( int n)
inline

Definition at line 40 of file SettingsPage.hpp.

40{ if (n >= 0 && static_cast<size_t>(n) < page_order_.size()) stack.set_visible_child(*page_order_[n]); }

References page_order_, and stack.

Referenced by SettingsWindow::build_sidebar(), and SettingsWindow::SettingsWindow().

◆ is_system_service_enabled()

bool SettingsPage::is_system_service_enabled ( const std::string & unit_name)
private

Definition at line 4457 of file SettingsPage.cpp.

4458{
4459 try
4460 {
4461 auto proc = Gio::Subprocess::create(
4462 {"/usr/libexec/bastionguard/bastionguard-service", "--system", "is-enabled", unit_name},
4463 Gio::Subprocess::Flags::STDOUT_PIPE |
4464 Gio::Subprocess::Flags::STDERR_PIPE
4465 );
4466
4467 proc->wait();
4468 auto [stdout_str, stderr_str] = proc->communicate_utf8("");
4469
4470 if (!proc->get_successful())
4471 return false;
4472
4473 std::string result = stdout_str.raw();
4474 result.erase(std::remove(result.begin(), result.end(), '\n'), result.end());
4475 result.erase(std::remove(result.begin(), result.end(), '\r'), result.end());
4476
4477 return result == "enabled";
4478 }
4479 catch (...)
4480 {
4481 return false;
4482 }
4483}

Referenced by build_services_section().

◆ is_user_service_enabled()

bool SettingsPage::is_user_service_enabled ( const std::string & service_name)
private

Definition at line 4413 of file SettingsPage.cpp.

4414{
4415 try
4416 {
4417 auto proc = Gio::Subprocess::create(
4418 {"/usr/libexec/bastionguard/bastionguard-service", "--user", "is-enabled", service_name},
4419 Gio::Subprocess::Flags::STDOUT_PIPE |
4420 Gio::Subprocess::Flags::STDERR_PIPE
4421 );
4422
4423 proc->wait();
4424 auto [stdout_str, stderr_str] = proc->communicate_utf8("");
4425
4426 if (!proc->get_successful())
4427 return false;
4428
4429 std::string result = stdout_str.raw();
4430 result.erase(std::remove(result.begin(), result.end(), '\n'), result.end());
4431 result.erase(std::remove(result.begin(), result.end(), '\r'), result.end());
4432
4433 return result == "enabled";
4434 }
4435 catch (...)
4436 {
4437 return false;
4438 }
4439}

Referenced by build_services_section().

◆ loadAdvancedConfig()

void SettingsPage::loadAdvancedConfig ( )
private

Definition at line 4634 of file SettingsPage.cpp.

4634 {
4635 try {
4636 std::string conf_file = Glib::get_home_dir() + "/.config/BastionGuard/scanner.conf";
4637 if (!std::filesystem::exists(conf_file))
4638 return;
4639
4640 std::ifstream in(conf_file);
4641 if (!in.is_open()) return;
4642
4643 std::string line;
4644 std::regex re("^\\s*([^#=]+?)\\s*=\\s*(.*?)\\s*$");
4645 std::smatch m;
4646
4647 bool susp = false;
4648 Glib::ustring ign_paths, ign_ext, susp_ext;
4649
4650 while (std::getline(in, line)) {
4651 if (line.empty() || line[0] == '#') continue;
4652 if (std::regex_match(line, m, re)) {
4653 std::string key = m[1], val = m[2];
4654 if (key == "suspicious_only") susp = (val == "1" || val == "true");
4655 else if (key == "ignore_paths") ign_paths = val;
4656 else if (key == "ignore_ext") ign_ext = val;
4657 else if (key == "suspicious_ext") susp_ext = val;
4658 }
4659 }
4660
4661 if (chkSuspOnly) chkSuspOnly->set_active(susp);
4662 if (txtIgnPaths) txtIgnPaths->set_text(ign_paths);
4663 if (txtIgnExt) txtIgnExt->set_text(ign_ext);
4664 if (txtSuspExt) txtSuspExt->set_text(susp_ext);
4665
4666 std::cout << _("[SettingsPage] 🔄 Configurazione caricata da ") << conf_file << std::endl;
4667
4668 } catch (const std::exception& ex) {
4669 std::cerr << _("[SettingsPage] ⚠ Errore caricando configurazione: ") << ex.what() << std::endl;
4670 }
4671}

References _, chkSuspOnly, txtIgnExt, txtIgnPaths, and txtSuspExt.

Referenced by build_antiransom_advanced_tab(), saveAdvancedConfig(), and SettingsPage().

◆ loadAllowlistUI()

void SettingsPage::loadAllowlistUI ( )
private

Definition at line 4509 of file SettingsPage.cpp.

4509 {
4510 allowStore->clear();
4511 std::ifstream f("config/allowlist.txt");
4512 if (!f.is_open()) return;
4513 std::string line;
4514 while (std::getline(f, line)) {
4515 if (line.empty() || line[0] == '#') continue;
4516 std::string sha, rule;
4517 auto semi = line.find(';');
4518 if (semi == std::string::npos) sha = line;
4519 else { sha = line.substr(0, semi); rule = line.substr(semi + 1); }
4520 auto row = *(allowStore->append());
4521 row[allowCols.col_hash] = Glib::ustring(sha);
4522 row[allowCols.col_rule] = Glib::ustring(rule);
4523 }
4524}

References allowCols, allowStore, SettingsPage::AllowlistCols::col_hash, and SettingsPage::AllowlistCols::col_rule.

Referenced by build_antiransom_advanced_tab().

◆ loadPhishLists()

void SettingsPage::loadPhishLists ( )
private

Definition at line 2429 of file SettingsPage.cpp.

2429 {
2430 if (!phishStore) {
2431 std::cerr << _("⚠ phishStore non inizializzato\n");
2432 return;
2433 }
2434
2435 phishStore->clear();
2436 std::string reducePath = resource("phishing/blacklist-reduce.txt");
2437 std::ifstream freduce(reducePath);
2438 if (freduce.is_open()) {
2439 std::string line;
2440 int count = 0;
2441 while (std::getline(freduce, line)) {
2442 if (!line.empty()) {
2443 auto row = *(phishStore->append());
2444 row[phishCols.source] = line;
2445 count++;
2446 }
2447 }
2448 freduce.close();
2449
2450 if (count == 0) {
2451 auto row = *(phishStore->append());
2452 row[phishCols.source] = "⚠ " + std::string(_("Blacklist ridotta vuota in ")) + reducePath;
2453 } else {
2454 auto row = *(phishStore->append());
2455 row[phishCols.source] = "✔ " + std::string(_("Caricate ")) + std::to_string(count) +
2456 " " + std::string(_("righe da blacklist ridotta"));
2457 }
2458 } else {
2459 auto row = *(phishStore->append());
2460 row[phishCols.source] = "⚠ " + std::string(_("Nessuna blacklist ridotta trovata in ")) + reducePath;
2461 }
2462 std::string fullPath = resource("phishing/blacklist.txt");
2463 if (std::filesystem::exists(fullPath)) {
2464 auto row = *(phishStore->append());
2465 row[phishCols.source] = "✔ " + std::string(_("Lista completa in ")) + fullPath;
2466 } else {
2467 auto row = *(phishStore->append());
2468 row[phishCols.source] = "⚠ " + std::string(_("Lista completa non trovata in ")) + fullPath;
2469 }
2470}
std::string resource(const std::string &rel)
Definition Resource.hpp:31

References _, phishCols, phishStore, resource(), and SettingsPage::PhishColumns::source.

Referenced by build_antiphish_tab(), and refreshPhishLists().

◆ loadPreference()

void SettingsPage::loadPreference ( )
private

Definition at line 239 of file SettingsPage.cpp.

240{
241 m_savedEnabled = true;
242
243 std::ifstream in(m_configPath);
244 std::string line;
245 while (std::getline(in, line)) {
246 if (line == "enabled=false") m_savedEnabled = false;
247 if (line == "enabled=true") m_savedEnabled = true;
248 if (line == "autostart_enabled=false") m_savedEnabled = false;
249 if (line == "daemon_enabled=false") m_savedEnabled = false;
250 }
251
252 m_updatingSwitch = true;
253 m_enableSwitch.set_active(m_savedEnabled);
254 m_updatingSwitch = false;
255}

References m_configPath, m_enableSwitch, m_savedEnabled, and m_updatingSwitch.

Referenced by refreshState(), and SettingsPage().

◆ loadScannerConfig()

void SettingsPage::loadScannerConfig ( bool & use_rules,
bool & use_db,
int & interval,
std::vector< std::string > & dirs )
private

Definition at line 1987 of file SettingsPage.cpp.

1989{
1990 use_rules = true;
1991 use_db = false;
1992 interval = 60;
1993 dirs.clear();
1994
1995 std::string conf_path = resource("config/scanner.conf");
1996
1997 std::ifstream f(conf_path);
1998 if (!f.is_open()) {
1999 std::cerr << _("⚠️ Config non trovata → uso default (/home)\n");
2000 dirs.push_back("/home");
2001 return;
2002 }
2003
2004 std::string line;
2005
2006 while (std::getline(f, line)) {
2007 if (line.empty() || line[0] == '#')
2008 continue;
2009
2010 std::string lower = line;
2011 std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
2012
2013 if (lower.find("enable_yara=") == 0) {
2014 std::string val = lower.substr(12);
2015 use_rules = (val == "1" || val == "true" || val == "yes");
2016 }
2017 else if (lower.find("enable_sanesecurity=") == 0) {
2018 std::string val = lower.substr(20);
2019 use_db = (val == "1" || val == "true" || val == "yes");
2020 }
2021 else if (lower.find("scan_interval=") == 0) {
2022 std::string val = lower.substr(14);
2023 try { interval = std::stoi(val); }
2024 catch (...) { interval = 60; }
2025 }
2026 else if (lower.find("scan_path=") == 0) {
2027 std::string paths = line.substr(10);
2028 size_t start = 0, end;
2029 while ((end = paths.find(';', start)) != std::string::npos) {
2030 dirs.push_back(paths.substr(start, end - start));
2031 start = end + 1;
2032 }
2033 if (start < paths.size())
2034 dirs.push_back(paths.substr(start));
2035 }
2036 }
2037
2038 if (dirs.empty())
2039 dirs.push_back("/home");
2040
2041 std::cout << _("✔ Config caricata da ") << conf_path
2042 << " (interval=" << interval << ")\n";
2043}

References _, and resource().

Referenced by build_antiransom_tab().

◆ loadYaraRules()

void SettingsPage::loadYaraRules ( )
private

Definition at line 1929 of file SettingsPage.cpp.

1929 {
1930 if (!rulesStore) {
1931 std::cerr << _("⚠ rulesStore non inizializzato\n");
1932 return;
1933 }
1934
1935 rulesStore->clear();
1936
1937 namespace fs = std::filesystem;
1938 std::string dir = "/usr/share/BastionGuard/data/yara";
1939
1940 if (!fs::exists(dir)) {
1941 std::cerr << _("⚠ Nessuna cartella YARA trovata in ") << dir << "\n";
1942 return;
1943 }
1944
1945 std::regex ruleRegex(R"(^\s*rule\s+([A-Za-z0-9_]+))");
1946 std::smatch match;
1947 int total_rules = 0;
1948
1949 std::error_code ec_it;
1950 for (auto& entry : fs::directory_iterator(dir, ec_it)) {
1951 if (ec_it) {
1952 std::cerr << _("⚠ Impossibile leggere la cartella YARA: ") << dir << "\n";
1953 break;
1954 }
1955 if (!entry.is_regular_file())
1956 continue;
1957
1958 std::string ext = entry.path().extension().string();
1959 std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
1960 if (ext != ".yar" && ext != ".yara")
1961 continue;
1962
1963 std::ifstream f(entry.path());
1964 if (!f.is_open()) {
1965 std::cerr << _("⚠ Impossibile aprire ") << entry.path() << "\n";
1966 continue;
1967 }
1968
1969 std::string line;
1970 while (std::getline(f, line)) {
1971 if (std::regex_search(line, match, ruleRegex)) {
1972 auto row = *(rulesStore->append());
1973 row[ruleCols.name] = match[1].str();
1974 total_rules++;
1975 }
1976 }
1977 }
1978
1979 if (total_rules > 0) {
1980 std::cout << "✔ " << total_rules << _(" regole YARA caricate da ") << dir << "\n";
1981 } else {
1982 std::cout << _("⚠ Nessuna regola YARA trovata in ") << dir << "\n";
1983 }
1984}

References _, SettingsPage::RuleColumns::name, ruleCols, and rulesStore.

Referenced by build_antiransom_tab(), and refreshAntiransomRules().

◆ onAddPath()

void SettingsPage::onAddPath ( )
private

Definition at line 1655 of file SettingsPage.cpp.

1655 {
1656 auto dialog = new Gtk::FileChooserDialog(_("Seleziona una cartella"),
1657 Gtk::FileChooser::Action::SELECT_FOLDER);
1658 dialog->add_button(_("_Annulla"), Gtk::ResponseType::CANCEL);
1659 dialog->add_button(_("_Seleziona"), Gtk::ResponseType::OK);
1660 dialog->set_modal(true);
1661
1662 dialog->signal_response().connect([this, dialog](int response) {
1663 if (response == Gtk::ResponseType::OK) {
1664 auto folder = dialog->get_file()->get_path();
1665 auto row = Gtk::make_managed<Gtk::Label>(folder);
1666 listbox_paths.append(*row);
1667 row->show();
1669 }
1670 dialog->hide();
1671 delete dialog;
1672 });
1673 dialog->show();
1674}
void addOnAccessPath(const std::string &path)

References _, ClamdConfig::addOnAccessPath(), clamdConfig, and listbox_paths.

Referenced by SettingsPage().

◆ onAddSambaDir()

void SettingsPage::onAddSambaDir ( )
private

◆ onAntiphishToggled()

void SettingsPage::onAntiphishToggled ( )
private

Definition at line 2395 of file SettingsPage.cpp.

2395 {
2396 if (antiphishSwitch.get_active()) {
2397 if (!isServiceActive("BastionGuard-phishing-scanner.service")) {
2398 antiphishStatus.set_text(_("⏳ Avvio servizio Anti-Phishing..."));
2399 if ((bg_process::run({"pkexec", "/usr/libexec/bastionguard/bastionguard-service", "--system", "start", "BastionGuard-phishing-scanner.service"}).exit_code) != 0) {
2400 antiphishStatus.set_text(_("❌ Impossibile avviare il servizio Anti-Phishing"));
2401 antiphishSwitch.set_active(false);
2402 return;
2403 }
2404 }
2406 antiphishStatus.set_text(_("Protezione Anti-Phishing: Attiva"));
2407 } else {
2408 if (isServiceActive("BastionGuard-phishing-scanner.service")) {
2409 antiphishStatus.set_text(_("⏳ Arresto servizio Anti-Phishing..."));
2410 if ((bg_process::run({"pkexec", "/usr/libexec/bastionguard/bastionguard-service", "--system", "stop", "BastionGuard-phishing-scanner.service"}).exit_code) != 0) {
2411 antiphishStatus.set_text(_("❌ Impossibile fermare il servizio Anti-Phishing"));
2412 antiphishSwitch.set_active(true);
2413 return;
2414 }
2415 }
2417 antiphishStatus.set_text(_("Protezione Anti-Phishing: Disattivata"));
2418 }
2419}
void stop_antiphish()
Definition Backend.cpp:1530
void start_antiphish()
Definition Backend.cpp:1520

References _, antiphishStatus, antiphishSwitch, bg_process::Result::exit_code, Backend::instance(), bg_process::run(), Backend::start_antiphish(), and Backend::stop_antiphish().

Referenced by build_antiphish_tab().

◆ onAntiransomToggled()

void SettingsPage::onAntiransomToggled ( )
private

Definition at line 1891 of file SettingsPage.cpp.

1891 {
1892 if (antiransomSwitch.get_active()) {
1893 if (!isServiceActive("BastionGuard-ransomware-scanner.service", true)) {
1894 antiransomStatus.set_text(_("⏳ Avvio servizio Anti-Ransomware..."));
1895 if ((bg_process::run({"/usr/libexec/bastionguard/bastionguard-service", "--user", "start", "BastionGuard-ransomware-scanner.service"}).exit_code) != 0) {
1896 antiransomStatus.set_text(_("❌ Impossibile avviare il servizio Anti-Ransomware"));
1897 antiransomSwitch.set_active(false);
1898 return;
1899 }
1900 }
1902 antiransomStatus.set_text(_("Protezione Anti-Ransomware: Attiva"));
1903 } else {
1904 if (isServiceActive("BastionGuard-ransomware-scanner.service", true)) {
1905 antiransomStatus.set_text(_("⏳ Arresto servizio Anti-Ransomware..."));
1906 if ((bg_process::run({"/usr/libexec/bastionguard/bastionguard-service", "--user", "stop", "BastionGuard-ransomware-scanner.service"}).exit_code) != 0) {
1907 antiransomStatus.set_text(_("❌ Impossibile fermare il servizio Anti-Ransomware"));
1908 antiransomSwitch.set_active(true);
1909 return;
1910 }
1911 }
1913 antiransomStatus.set_text(_("Protezione Anti-Ransomware: Disattivata"));
1914 }
1915}
void stop_antiransom()
Definition Backend.cpp:847
void start_antiransom()
Definition Backend.cpp:837

References _, antiransomStatus, antiransomSwitch, bg_process::Result::exit_code, Backend::instance(), bg_process::run(), Backend::start_antiransom(), and Backend::stop_antiransom().

Referenced by build_antiransom_tab().

◆ onQuarantineClicked()

void SettingsPage::onQuarantineClicked ( )
private

Definition at line 1635 of file SettingsPage.cpp.

1635 {
1636 auto dialog = new Gtk::FileChooserDialog(_("Seleziona una cartella quarantena"),
1637 Gtk::FileChooser::Action::SELECT_FOLDER);
1638 dialog->add_button(_("_Annulla"), Gtk::ResponseType::CANCEL);
1639 dialog->add_button(_("_Seleziona"), Gtk::ResponseType::OK);
1640 dialog->set_modal(true);
1641 dialog->get_style_context()->add_class("app-dialog");
1642
1643 dialog->signal_response().connect([this, dialog](int response) {
1644 if (response == Gtk::ResponseType::OK) {
1645 std::string folder = dialog->get_file()->get_path();
1647 quarantineLabel.set_text(_("Percorso quarantena: ") + folder);
1648 }
1649 dialog->hide();
1650 delete dialog;
1651 });
1652 dialog->show();
1653}
static void setQuarantinePath(const std::string &path)
Definition Backend.cpp:490

References _, quarantineLabel, and Backend::setQuarantinePath().

Referenced by SettingsPage().

◆ onRealtimeToggled()

void SettingsPage::onRealtimeToggled ( )
private

Definition at line 1712 of file SettingsPage.cpp.

1712 {
1713 realtimeLabel.set_text(clamonaccSwitch.get_active() ?
1714 _("Antivirus real time: Abilitato") :
1715 _("Antivirus real time: Disabilitato"));
1716}

References _, clamonaccSwitch, and realtimeLabel.

Referenced by SettingsPage().

◆ onRemovePath()

void SettingsPage::onRemovePath ( )
private

Definition at line 1676 of file SettingsPage.cpp.

1676 {
1677 if (auto row = listbox_paths.get_selected_row()) {
1678 if (auto child = row->get_child()) {
1679 if (auto label = dynamic_cast<Gtk::Label*>(child)) {
1680 clamdConfig.removeOnAccessPath(label->get_text());
1681 }
1682 }
1683 listbox_paths.remove(*row);
1684 }
1685}
void removeOnAccessPath(const std::string &path)

References clamdConfig, listbox_paths, and ClamdConfig::removeOnAccessPath().

Referenced by SettingsPage().

◆ onRemoveSambaDir()

void SettingsPage::onRemoveSambaDir ( )
private

◆ onSave()

void SettingsPage::onSave ( )
private

Definition at line 1687 of file SettingsPage.cpp.

1687 {
1688 for (auto& [opt, cb] : checkOptions) {
1689 clamdConfig.setScanOption(opt, cb->get_active());
1690 }
1691 const std::string target = choose_clamd_conf_target();
1692 const std::string tmp_path = "/tmp/BastionGuard-clamd.conf.tmp";
1693 if (!clamdConfig.save(tmp_path)) {
1694 std::cerr << "❌ " << _("Errore: impossibile scrivere il file temporaneo di configurazione")
1695 << " " << tmp_path << "\n";
1696 return;
1697 }
1698
1699 if (atomic_install_with_pkexec(tmp_path, target)) {
1700 std::cout << "✔ " << _("Configurazione salvata su") << " " << target << "\n";
1701 } else {
1702 std::cerr << "❌ " << _("Errore: impossibile salvare configurazione!")
1703 << " (" << target << ")\n";
1704 }
1705
1707 std::cerr << "⚠ " << _("Errore: impossibile installare clamd automaticamente.") << "\n";
1708 }
1709}
static bool installClamdIfMissing()
Definition Backend.cpp:664
void setScanOption(const std::string &key, bool enabled)
bool save(const std::string &path)
bool atomic_install_with_pkexec(const std::string &tmp_src, const std::string &target)

References _, checkOptions, clamdConfig, Backend::installClamdIfMissing(), ClamdConfig::save(), and ClamdConfig::setScanOption().

Referenced by SettingsPage().

◆ onScanNowSamba()

void SettingsPage::onScanNowSamba ( )
private

◆ pkexec_servicectl()

bool SettingsPage::pkexec_servicectl ( const std::vector< std::string > & args,
std::string * out_stdout = nullptr )
private

Definition at line 4399 of file SettingsPage.cpp.

4401{
4402 std::vector<std::string> argv;
4403 argv.reserve(args.size() + 3);
4404 argv.push_back("pkexec");
4405 argv.push_back("/usr/libexec/bastionguard/bastionguard-service");
4406 argv.push_back("--system");
4407 argv.insert(argv.end(), args.begin(), args.end());
4408
4409 return run_cmd(argv, out_stdout, false);
4410}

References run_cmd().

Referenced by disable_system_service(), and enable_system_service().

◆ refresh_clamav_db_list()

void SettingsPage::refresh_clamav_db_list ( Gtk::Box * listBox)
private

Definition at line 4726 of file SettingsPage.cpp.

4727{
4728 if (!listBox) return;
4729
4730 auto children = listBox->get_children();
4731 for (auto* w : children)
4732 listBox->remove(*w);
4733
4734 const std::filesystem::path clamdb = "/var/lib/clamav";
4735 auto sigs = list_clamav_signatures(clamdb);
4736
4737 if (clamdb_count_label_) {
4738 clamdb_count_label_->set_text(
4739 Glib::ustring::compose(_("Firme trovate: %1"), sigs.size())
4740 );
4741 }
4742
4743 if (sigs.empty())
4744 {
4745 auto lbl = Gtk::make_managed<Gtk::Label>(
4746 _("Nessuna firma trovata in /var/lib/clamav")
4747 );
4748 lbl->set_xalign(0.0);
4749 lbl->add_css_class("alert-warning");
4750 listBox->append(*lbl);
4751 return;
4752 }
4753
4754 for (const auto& p : sigs)
4755 {
4756 auto lbl = Gtk::make_managed<Gtk::Label>(p.filename().string());
4757 lbl->set_xalign(0.0);
4758 lbl->add_css_class("readonly-path");
4759 listBox->append(*lbl);
4760 }
4761}
static std::vector< std::filesystem::path > list_clamav_signatures(const std::filesystem::path &dir)

References _, clamdb_count_label_, and list_clamav_signatures().

Referenced by build_clamav_db_tab().

◆ refreshAntiransomRules()

void SettingsPage::refreshAntiransomRules ( )
private

Definition at line 1920 of file SettingsPage.cpp.

1920 {
1921 if (!rulesStore) {
1922 std::cerr << _("⚠ refreshAntiransomRules chiamata ma rulesStore non è inizializzato\n");
1923 return;
1924 }
1925 loadYaraRules();
1926}

References _, loadYaraRules(), and rulesStore.

Referenced by build_antiransom_tab().

◆ refreshPhishLists()

void SettingsPage::refreshPhishLists ( )
private

Definition at line 2421 of file SettingsPage.cpp.

2421 {
2422 if (!phishStore) {
2423 std::cerr << _("⚠ refreshPhishLists chiamata ma phishStore non è inizializzato\n");
2424 return;
2425 }
2427}

References _, loadPhishLists(), and phishStore.

Referenced by build_antiphish_tab().

◆ refreshState()

void SettingsPage::refreshState ( )

Definition at line 283 of file SettingsPage.cpp.

284{
286
287 const bool svc = serviceEnabled();
288 const bool autoStart = autostartInstalled();
289 const bool backup = backupExists();
290
291 const bool protectionActive = m_savedEnabled && svc && autoStart;
292 const bool protectionInactive = !m_savedEnabled && !svc && !autoStart;
293 const bool protectionPartial = !protectionActive && !protectionInactive;
294
295 m_savedPrefLabel.set_text(
296 _("Preferenza salvata in ~/.config: ") +
297 std::string(m_savedEnabled ? _("attivo") : _("disattivato")));
298
299 m_serviceStateLabel.set_text(
300 _("Servizio di sistema abilitato: ") + boolText(svc));
301
302 m_autostartStateLabel.set_text(
303 _("Autostart presente in /etc/xdg/autostart: ") + boolText(autoStart));
304
305 m_backupStateLabel.set_text(
306 _("Backup autostart in /etc/xdg/autostart disponibile: ") + boolText(backup));
307
308 if (m_statusLabel.get_text().empty()) {
309 m_statusLabel.set_text(
310 _("Usa questa pagina per applicare o ripristinare la configurazione di avvio di BastionGuard."));
311 }
312
313 if (protectionActive) {
314 m_serviceBadge.set_text(_("Attivo"));
315 m_detailsBadge.set_text(_("Coerente"));
316 set_badge_class(m_serviceBadge, "status-badge-success");
317 set_badge_class(m_detailsBadge, "status-badge-success");
318 } else if (protectionInactive) {
319 m_serviceBadge.set_text(_("Disattivato"));
320 m_detailsBadge.set_text(_("Disattivato"));
321 set_badge_class(m_serviceBadge, "status-badge-danger");
322 set_badge_class(m_detailsBadge, "status-badge-danger");
323 } else if (protectionPartial) {
324 m_serviceBadge.set_text(_("Parziale"));
325 m_detailsBadge.set_text(_("Incoerente"));
326 set_badge_class(m_serviceBadge, "status-badge-warning");
327 set_badge_class(m_detailsBadge, "status-badge-warning");
328 } else {
329 m_serviceBadge.set_text(_("Info"));
330 m_detailsBadge.set_text(_("Info"));
331 set_badge_class(m_serviceBadge, "status-badge-info");
332 set_badge_class(m_detailsBadge, "status-badge-info");
333 }
334
335 m_updatingSwitch = true;
336 m_enableSwitch.set_active(m_savedEnabled);
337 m_updatingSwitch = false;
338}
bool autostartInstalled() const
static std::string boolText(bool value)
bool backupExists() const
bool serviceEnabled() const
void set_badge_class(Gtk::Widget &w, const char *css_class)

References _, autostartInstalled(), backupExists(), boolText(), loadPreference(), m_autostartStateLabel, m_backupStateLabel, m_detailsBadge, m_enableSwitch, m_savedEnabled, m_savedPrefLabel, m_serviceBadge, m_serviceStateLabel, m_statusLabel, m_updatingSwitch, and serviceEnabled().

Referenced by MainWindow::applyProtectionEnabled(), buildUi(), MainWindow::refreshSystemIntegrationStatus(), and SettingsPage().

◆ run_cmd()

bool SettingsPage::run_cmd ( const std::vector< std::string > & argv,
std::string * out_stdout = nullptr,
bool silence_stderr = true )
private

Definition at line 4673 of file SettingsPage.cpp.

4676{
4677 try
4678 {
4679 Gio::Subprocess::Flags flags = Gio::Subprocess::Flags::NONE;
4680
4681 if (out_stdout)
4682 flags |= Gio::Subprocess::Flags::STDOUT_PIPE;
4683
4684 if (silence_stderr)
4685 flags |= Gio::Subprocess::Flags::STDERR_SILENCE;
4686 else
4687 flags |= Gio::Subprocess::Flags::STDERR_PIPE;
4688
4689 auto proc = Gio::Subprocess::create(argv, flags);
4690 proc->wait();
4691
4692 if (out_stdout)
4693 {
4694 auto [stdout_str, stderr_str] = proc->communicate_utf8("");
4695 *out_stdout = stdout_str.raw();
4696 }
4697
4698 return proc->get_successful();
4699 }
4700 catch (...)
4701 {
4702 return false;
4703 }
4704}

Referenced by disable_user_service(), enable_user_service(), and pkexec_servicectl().

◆ saveAdvancedConfig()

void SettingsPage::saveAdvancedConfig ( bool suspicious_only,
const Glib::ustring & ignore_paths,
const Glib::ustring & ignore_ext,
const Glib::ustring & suspicious_ext )
private

Definition at line 4560 of file SettingsPage.cpp.

4564{
4565 namespace fs = std::filesystem;
4566 try {
4567 const char* real_user = getenv("SUDO_USER");
4568 if (!real_user || !*real_user)
4569 real_user = getenv("USER");
4570
4571 struct passwd* pw = getpwnam(real_user ? real_user : "root");
4572 std::string home_dir = pw ? pw->pw_dir : Glib::get_home_dir();
4573
4574 std::string conf_dir = home_dir + "/.config/BastionGuard";
4575 std::string conf_file = conf_dir + "/scanner.conf";
4576 fs::create_directories(conf_dir);
4577
4578 std::map<std::string, std::string> kv;
4579 std::vector<std::string> comments;
4580 if (fs::exists(conf_file)) {
4581 std::ifstream in(conf_file);
4582 std::string line;
4583 std::regex re("^\\s*([^#=]+?)\\s*=\\s*(.*?)\\s*$");
4584 std::smatch m;
4585 while (std::getline(in, line)) {
4586 if (line.empty() || line[0] == '#') {
4587 comments.push_back(line);
4588 continue;
4589 }
4590 if (std::regex_match(line, m, re))
4591 kv[m[1]] = m[2];
4592 }
4593 }
4594
4595 kv["suspicious_only"] = suspicious_only ? "1" : "0";
4596 kv["ignore_paths"] = ignore_paths.raw();
4597 kv["ignore_ext"] = ignore_ext.raw();
4598 kv["suspicious_ext"] = suspicious_ext.raw();
4599
4600 std::ofstream out(conf_file, std::ios::trunc);
4601 if (!out.is_open()) {
4602 std::cerr << _("[SettingsPage] ❌ Impossibile scrivere ") << conf_file << std::endl;
4603 return;
4604 }
4605
4606 out << _("# --- BastionGuard Anti-Ransomware Config ---\n");
4607 for (const auto& c : comments)
4608 if (!c.empty()) out << c << "\n";
4609
4610 for (const auto& [k, v] : kv)
4611 out << k << "=" << v << "\n";
4612
4613 out.close();
4614
4615 if (pw) chown(conf_file.c_str(), pw->pw_uid, pw->pw_gid);
4616 chmod(conf_file.c_str(), 0644);
4617
4618 std::cout << _("[SettingsPage] ✅ Config salvata in ") << conf_file << std::endl;
4619
4621
4622 Gtk::Window* parent = dynamic_cast<Gtk::Window*>(get_root());
4623 Utils::show_message(parent,
4624 _("Configurazione salvata correttamente."),
4625 Gtk::MessageType::INFO,
4626 _("Le impostazioni aggiornate sono state caricate e applicate.\n"
4627 "Non serve riavviare il programma."));
4628
4629 } catch (const std::exception& ex) {
4630 std::cerr << _("[SettingsPage] ⚠ Errore in saveAdvancedConfig: ") << ex.what() << std::endl;
4631 }
4632}

References _, loadAdvancedConfig(), and Utils::show_message().

Referenced by build_antiransom_advanced_tab().

◆ saveAllowlistUI()

void SettingsPage::saveAllowlistUI ( )
private

Definition at line 4528 of file SettingsPage.cpp.

4528 {
4529 std::string confPath = Glib::get_home_dir() + "/.config/BastionGuard/allowlist.txt";
4530
4531 std::filesystem::create_directories(Glib::get_home_dir() + "/.config/BastionGuard");
4532
4533 std::ofstream out(confPath, std::ios::trunc);
4534 if (!out.is_open()) {
4535 std::cerr << _("[SettingsPage] ❌ Impossibile scrivere ") << confPath << std::endl;
4536 return;
4537 }
4538
4539 for (const auto& row : allowStore->children()) {
4540 Glib::ustring sha = row[allowCols.col_hash];
4541 Glib::ustring rule = row[allowCols.col_rule];
4542
4543 if (sha.raw().empty())
4544 continue;
4545
4546 out << sha.raw();
4547 if (!rule.raw().empty())
4548 out << ";" << rule.raw();
4549 out << "\n";
4550 }
4551
4552 out.flush();
4553 out.close();
4554
4555 std::cout << _("[SettingsPage] ✅ Allowlist salvata in ") << confPath << std::endl;
4556}

References _, allowCols, allowStore, SettingsPage::AllowlistCols::col_hash, and SettingsPage::AllowlistCols::col_rule.

Referenced by build_antiransom_advanced_tab().

◆ saveScannerConfig()

void SettingsPage::saveScannerConfig ( bool use_rules,
bool use_db,
int interval,
const std::vector< std::string > & dirs )
private

Definition at line 2047 of file SettingsPage.cpp.

2049{
2050 namespace fs = std::filesystem;
2051 std::string save_path;
2052 bool use_local = false;
2053
2054 if (fs::exists("config"))
2055 save_path = "config/scanner.conf";
2056 else
2057 save_path = std::string(DATA_DIR) + "/config/scanner.conf";
2058
2059 std::string tmp_path = use_local ? save_path : "/tmp/BastionGuard-scanner.conf.tmp";
2060
2061 std::ofstream f(tmp_path, std::ios::trunc);
2062 if (!f.is_open()) {
2063 std::cerr << "❌ Impossibile scrivere config in " << tmp_path << "\n";
2064 return;
2065 }
2066
2067 f << "# ===============================\n";
2068 f << _("# Configurazione BastionGuard Ransomware Scanner\n");
2069 f << "# ===============================\n\n";
2070 f << "enable_yara=" << (use_rules ? "1" : "0") << "\n";
2071 f << "enable_sanesecurity=" << (use_db ? "1" : "0") << "\n";
2072 f << "scan_interval=" << interval << "\n";
2073 f << "scan_path=";
2074 for (size_t i = 0; i < dirs.size(); ++i) {
2075 f << dirs[i];
2076 if (i + 1 < dirs.size()) f << ";";
2077 }
2078 f << "\n";
2079
2080 f.close();
2081
2082 if (!use_local) {
2083 if (bg_process::run({"pkexec", "/usr/bin/install", "-D", "-m", "0644",
2084 tmp_path, save_path}).ok())
2085 std::cout << _("✔ Config aggiornata in: ") << save_path << "\n";
2086 else
2087 std::cerr << _("❌ Errore: impossibile aggiornare config in ") << save_path << "\n";
2088 } else {
2089 std::cout << _("✔ Config aggiornata in: ") << save_path << "\n";
2090 }
2091}

References _, DATA_DIR, bg_process::Result::ok(), and bg_process::run().

Referenced by build_antiransom_tab().

◆ serviceEnabled()

bool SettingsPage::serviceEnabled ( ) const
private

Definition at line 258 of file SettingsPage.cpp.

259{
260 const std::string cmd =
261 std::string(BSC_SERVICECTL_PATH) + " --system is-enabled " +
262 kServiceName + " >/dev/null 2>&1";
263 return std::system(cmd.c_str()) == 0;
264}
constexpr const char * kServiceName
#define BSC_SERVICECTL_PATH

References BSC_SERVICECTL_PATH.

Referenced by refreshState().

◆ set_notebook_no_tabs()

void SettingsPage::set_notebook_no_tabs ( )
inline

Definition at line 41 of file SettingsPage.hpp.

41{ stack_switcher.set_visible(false); }

References stack_switcher.

Referenced by SettingsWindow::SettingsWindow().

◆ setProtectionEnabled()

void SettingsPage::setProtectionEnabled ( bool enabled)

Definition at line 50 of file SettingsPage.cpp.

51{
52 m_savedEnabled = enabled;
53 m_updatingSwitch = true;
54 m_enableSwitch.set_active(enabled);
55 m_updatingSwitch = false;
56}

References m_enableSwitch, m_savedEnabled, and m_updatingSwitch.

Referenced by MainWindow::applyProtectionEnabled(), and MainWindow::refreshSystemIntegrationStatus().

◆ setSystemIntegrationStatus()

void SettingsPage::setSystemIntegrationStatus ( const std::string & text)

Definition at line 58 of file SettingsPage.cpp.

59{
60 m_statusLabel.set_text(text);
61}

References m_statusLabel.

Referenced by MainWindow::applyProtectionEnabled(), and MainWindow::refreshSystemIntegrationStatus().

◆ show_service_error_dialog()

void SettingsPage::show_service_error_dialog ( const Glib::ustring & message,
const std::string & service_name )
staticprivate

Definition at line 4707 of file SettingsPage.cpp.

4710{
4711 auto dlg = Gtk::AlertDialog::create(message);
4712 dlg->set_detail(
4713 Glib::ustring::compose(
4714 _("Servizio: %1\n\n"
4715 "Possibili cause:\n"
4716 "• Il file .service non esiste\n"
4717 "• Il gestore servizi utente non è disponibile\n"
4718 "• Problemi di permessi o path\n"
4719 "• Errore di sintassi nel file di servizio"),
4720 service_name
4721 )
4722 );
4723 dlg->show();
4724}

References _.

Referenced by build_services_section().

◆ signal_toggle_protection_requested()

sigc::signal< void(bool)> & SettingsPage::signal_toggle_protection_requested ( )
inline

Definition at line 14 of file SettingsPage.hpp.

References m_signalToggleProtectionRequested.

◆ validate_samba_dirs()

bool SettingsPage::validate_samba_dirs ( )
private

Member Data Documentation

◆ alive_

◆ allowCols

AllowlistCols SettingsPage::allowCols
private

◆ allowStore

Glib::RefPtr<Gtk::ListStore> SettingsPage::allowStore
private

◆ allowView

Gtk::TreeView SettingsPage::allowView
private

Definition at line 179 of file SettingsPage.hpp.

Referenced by build_antiransom_advanced_tab().

◆ antiphishStatus

Gtk::Label SettingsPage::antiphishStatus
private

Definition at line 125 of file SettingsPage.hpp.

Referenced by build_antiphish_tab(), and onAntiphishToggled().

◆ antiphishSwitch

Gtk::Switch SettingsPage::antiphishSwitch
private

Definition at line 124 of file SettingsPage.hpp.

Referenced by build_antiphish_tab(), and onAntiphishToggled().

◆ antiransomStatus

Gtk::Label SettingsPage::antiransomStatus
private

◆ antiransomSwitch

Gtk::Switch SettingsPage::antiransomSwitch
private

Definition at line 83 of file SettingsPage.hpp.

Referenced by build_antiransom_tab(), onAntiransomToggled(), and SettingsPage().

◆ box_scanOptions

Gtk::Box SettingsPage::box_scanOptions {Gtk::Orientation::VERTICAL}
private

Definition at line 59 of file SettingsPage.hpp.

◆ btn_addPath

Gtk::Button SettingsPage::btn_addPath
private

Definition at line 56 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ btn_addScanPath

Gtk::Button SettingsPage::btn_addScanPath
private

Definition at line 99 of file SettingsPage.hpp.

◆ btn_apply_language_

Gtk::Button SettingsPage::btn_apply_language_
private

Definition at line 144 of file SettingsPage.hpp.

Referenced by build_options_tab().

◆ btn_apply_webconfig_

Gtk::Button SettingsPage::btn_apply_webconfig_
private

Definition at line 80 of file SettingsPage.hpp.

Referenced by build_options_tab().

◆ btn_applyBase

Gtk::Button SettingsPage::btn_applyBase
private

Definition at line 66 of file SettingsPage.hpp.

◆ btn_removePath

Gtk::Button SettingsPage::btn_removePath
private

Definition at line 57 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ btn_removeScanPath

Gtk::Button SettingsPage::btn_removeScanPath
private

Definition at line 100 of file SettingsPage.hpp.

◆ btn_save

Gtk::Button SettingsPage::btn_save
private

Definition at line 65 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ btnAddSamba

Gtk::Button SettingsPage::btnAddSamba
private

Definition at line 107 of file SettingsPage.hpp.

◆ btnRemSamba

Gtk::Button SettingsPage::btnRemSamba
private

Definition at line 107 of file SettingsPage.hpp.

◆ btnScanNow

Gtk::Button SettingsPage::btnScanNow
private

Definition at line 107 of file SettingsPage.hpp.

◆ checkOptions

std::map<std::string, Gtk::CheckButton*> SettingsPage::checkOptions
private

Definition at line 60 of file SettingsPage.hpp.

Referenced by onSave(), and SettingsPage().

◆ chk_enableSamba

Gtk::CheckButton SettingsPage::chk_enableSamba
private

Definition at line 106 of file SettingsPage.hpp.

◆ chk_enableSanesecurity

Gtk::CheckButton SettingsPage::chk_enableSanesecurity
private

Definition at line 96 of file SettingsPage.hpp.

◆ chk_enableYara

Gtk::CheckButton SettingsPage::chk_enableYara
private

Definition at line 95 of file SettingsPage.hpp.

◆ chkSuspOnly

Gtk::CheckButton* SettingsPage::chkSuspOnly = nullptr
private

Definition at line 153 of file SettingsPage.hpp.

Referenced by build_antiransom_advanced_tab(), and loadAdvancedConfig().

◆ clamdb_count_label_

Gtk::Label* SettingsPage::clamdb_count_label_ = nullptr
private

Definition at line 73 of file SettingsPage.hpp.

Referenced by build_clamav_db_tab(), and refresh_clamav_db_list().

◆ clamdConfig

ClamdConfig& SettingsPage::clamdConfig
private

Definition at line 43 of file SettingsPage.hpp.

Referenced by onAddPath(), onRemovePath(), onSave(), and SettingsPage().

◆ clamonaccSwitch

Gtk::Switch SettingsPage::clamonaccSwitch
private

Definition at line 50 of file SettingsPage.hpp.

Referenced by onRealtimeToggled(), and SettingsPage().

◆ combo_language_

Gtk::ComboBoxText SettingsPage::combo_language_
private

Definition at line 143 of file SettingsPage.hpp.

Referenced by build_options_tab().

◆ combo_os_

Gtk::ComboBoxText SettingsPage::combo_os_
private

Definition at line 75 of file SettingsPage.hpp.

Referenced by build_options_tab().

◆ enable_samba

bool SettingsPage::enable_samba = false
private

Definition at line 111 of file SettingsPage.hpp.

◆ entry_http_port_

Gtk::Entry SettingsPage::entry_http_port_
private

Definition at line 76 of file SettingsPage.hpp.

Referenced by build_options_tab().

◆ entry_https_port_

Gtk::Entry SettingsPage::entry_https_port_
private

Definition at line 77 of file SettingsPage.hpp.

Referenced by build_options_tab().

◆ googleSafeKeyEntry

Gtk::Entry SettingsPage::googleSafeKeyEntry
private

Definition at line 130 of file SettingsPage.hpp.

Referenced by build_antiphish_tab().

◆ googleSafeSwitch

Gtk::Switch SettingsPage::googleSafeSwitch
private

Definition at line 129 of file SettingsPage.hpp.

Referenced by build_antiphish_tab().

◆ http_updating_

bool SettingsPage::http_updating_ = false
private

Definition at line 78 of file SettingsPage.hpp.

◆ https_updating_

bool SettingsPage::https_updating_ = false
private

Definition at line 79 of file SettingsPage.hpp.

◆ lbl_scanPaths

Gtk::Label SettingsPage::lbl_scanPaths
private

Definition at line 97 of file SettingsPage.hpp.

◆ listbox_paths

Gtk::ListBox SettingsPage::listbox_paths
private

Definition at line 54 of file SettingsPage.hpp.

Referenced by onAddPath(), onRemovePath(), and SettingsPage().

◆ listbox_scanPaths

Gtk::ListBox SettingsPage::listbox_scanPaths
private

Definition at line 98 of file SettingsPage.hpp.

◆ m_applyButton

Gtk::Button SettingsPage::m_applyButton
private

Definition at line 29 of file SettingsPage.hpp.

Referenced by buildUi(), and SettingsPage().

◆ m_autostartStateLabel

Gtk::Label SettingsPage::m_autostartStateLabel
private

Definition at line 36 of file SettingsPage.hpp.

Referenced by buildUi(), and refreshState().

◆ m_backupPath

std::string SettingsPage::m_backupPath
private

Definition at line 45 of file SettingsPage.hpp.

Referenced by backupExists(), and SettingsPage().

◆ m_backupStateLabel

Gtk::Label SettingsPage::m_backupStateLabel
private

Definition at line 37 of file SettingsPage.hpp.

Referenced by buildUi(), and refreshState().

◆ m_configPath

std::string SettingsPage::m_configPath
private

Definition at line 44 of file SettingsPage.hpp.

Referenced by loadPreference(), and SettingsPage().

◆ m_content

Gtk::Box SettingsPage::m_content {Gtk::Orientation::VERTICAL, 16}
private

Definition at line 18 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_detailsBadge

Gtk::Label SettingsPage::m_detailsBadge
private

Definition at line 41 of file SettingsPage.hpp.

Referenced by buildUi(), and refreshState().

◆ m_detailsBox

Gtk::Box SettingsPage::m_detailsBox {Gtk::Orientation::VERTICAL, 8}
private

Definition at line 33 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_detailsFrame

Gtk::Frame SettingsPage::m_detailsFrame
private

Definition at line 32 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_detailsTitle

Gtk::Label SettingsPage::m_detailsTitle
private

Definition at line 40 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_enableLabel

Gtk::Label SettingsPage::m_enableLabel
private

Definition at line 26 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_enableSwitch

Gtk::Switch SettingsPage::m_enableSwitch
private

Definition at line 25 of file SettingsPage.hpp.

Referenced by buildUi(), loadPreference(), refreshState(), and setProtectionEnabled().

◆ m_infoLabel

Gtk::Label SettingsPage::m_infoLabel
private

Definition at line 28 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_intro

Gtk::Label SettingsPage::m_intro
private

Definition at line 21 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_refreshButton

Gtk::Button SettingsPage::m_refreshButton
private

Definition at line 30 of file SettingsPage.hpp.

Referenced by buildUi(), and SettingsPage().

◆ m_savedEnabled

bool SettingsPage::m_savedEnabled = true
private

Definition at line 46 of file SettingsPage.hpp.

Referenced by loadPreference(), refreshState(), and setProtectionEnabled().

◆ m_savedPrefLabel

Gtk::Label SettingsPage::m_savedPrefLabel
private

Definition at line 34 of file SettingsPage.hpp.

Referenced by buildUi(), and refreshState().

◆ m_scroll

Gtk::ScrolledWindow SettingsPage::m_scroll
private

Definition at line 17 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_serviceBadge

Gtk::Label SettingsPage::m_serviceBadge
private

Definition at line 39 of file SettingsPage.hpp.

Referenced by buildUi(), and refreshState().

◆ m_serviceBox

Gtk::Box SettingsPage::m_serviceBox {Gtk::Orientation::VERTICAL, 12}
private

Definition at line 24 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_serviceFrame

Gtk::Frame SettingsPage::m_serviceFrame
private

Definition at line 23 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_serviceStateLabel

Gtk::Label SettingsPage::m_serviceStateLabel
private

Definition at line 35 of file SettingsPage.hpp.

Referenced by buildUi(), and refreshState().

◆ m_serviceTitle

Gtk::Label SettingsPage::m_serviceTitle
private

Definition at line 38 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_signalToggleProtectionRequested

sigc::signal<void(bool)> SettingsPage::m_signalToggleProtectionRequested
private

Definition at line 43 of file SettingsPage.hpp.

Referenced by buildUi(), and signal_toggle_protection_requested().

◆ m_statusLabel

Gtk::Label SettingsPage::m_statusLabel
private

Definition at line 27 of file SettingsPage.hpp.

Referenced by buildUi(), refreshState(), and setSystemIntegrationStatus().

◆ m_title

Gtk::Label SettingsPage::m_title
private

Definition at line 20 of file SettingsPage.hpp.

Referenced by buildUi().

◆ m_updatingSwitch

bool SettingsPage::m_updatingSwitch = false
private

Definition at line 42 of file SettingsPage.hpp.

Referenced by buildUi(), loadPreference(), refreshState(), and setProtectionEnabled().

◆ page_order_

◆ phishCols

PhishColumns SettingsPage::phishCols
private

Definition at line 140 of file SettingsPage.hpp.

Referenced by build_antiphish_tab(), and loadPhishLists().

◆ phishStore

Glib::RefPtr<Gtk::ListStore> SettingsPage::phishStore
private

Definition at line 127 of file SettingsPage.hpp.

Referenced by build_antiphish_tab(), loadPhishLists(), and refreshPhishLists().

◆ phishView

Gtk::TreeView SettingsPage::phishView
private

Definition at line 128 of file SettingsPage.hpp.

Referenced by build_antiphish_tab().

◆ quarantineButton

Gtk::Button SettingsPage::quarantineButton
private

Definition at line 53 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ quarantineLabel

Gtk::Label SettingsPage::quarantineLabel
private

Definition at line 52 of file SettingsPage.hpp.

Referenced by onQuarantineClicked(), and SettingsPage().

◆ realtimeLabel

Gtk::Label SettingsPage::realtimeLabel
private

Definition at line 51 of file SettingsPage.hpp.

Referenced by onRealtimeToggled(), and SettingsPage().

◆ ruleCols

RuleColumns SettingsPage::ruleCols
private

Definition at line 91 of file SettingsPage.hpp.

Referenced by build_antiransom_tab(), and loadYaraRules().

◆ rulesStore

Glib::RefPtr<Gtk::ListStore> SettingsPage::rulesStore
private

Definition at line 92 of file SettingsPage.hpp.

Referenced by build_antiransom_tab(), loadYaraRules(), and refreshAntiransomRules().

◆ rulesView

Gtk::TreeView SettingsPage::rulesView
private

Definition at line 93 of file SettingsPage.hpp.

Referenced by build_antiransom_tab().

◆ samba_dirs

std::vector<std::string> SettingsPage::samba_dirs
private

Definition at line 112 of file SettingsPage.hpp.

◆ sambaCols

SambaColumns SettingsPage::sambaCols
private

Definition at line 103 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ sambaStore

Glib::RefPtr<Gtk::ListStore> SettingsPage::sambaStore
private

Definition at line 104 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ sambaView

Gtk::TreeView SettingsPage::sambaView
private

Definition at line 105 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ spin_interval

Gtk::SpinButton SettingsPage::spin_interval
private

Definition at line 101 of file SettingsPage.hpp.

Referenced by build_antiransom_tab().

◆ stack

◆ stack_switcher

Gtk::StackSwitcher SettingsPage::stack_switcher
private

Definition at line 46 of file SettingsPage.hpp.

Referenced by set_notebook_no_tabs(), and SettingsPage().

◆ switchEnableSamba

Gtk::Switch SettingsPage::switchEnableSamba
private

Definition at line 108 of file SettingsPage.hpp.

◆ toggleAllLabel

Gtk::Label SettingsPage::toggleAllLabel
private

Definition at line 63 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ toggleAllSwitch

Gtk::Switch SettingsPage::toggleAllSwitch
private

Definition at line 62 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ toggleControlled

std::map<std::string, bool> SettingsPage::toggleControlled
private

Definition at line 228 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ txtCompany

Gtk::Entry* SettingsPage::txtCompany = nullptr
private

Definition at line 155 of file SettingsPage.hpp.

Referenced by build_antiransom_advanced_tab().

◆ txtIgnExt

Gtk::Entry* SettingsPage::txtIgnExt = nullptr
private

Definition at line 156 of file SettingsPage.hpp.

Referenced by build_antiransom_advanced_tab(), and loadAdvancedConfig().

◆ txtIgnPaths

Gtk::Entry* SettingsPage::txtIgnPaths = nullptr
private

Definition at line 154 of file SettingsPage.hpp.

Referenced by build_antiransom_advanced_tab(), and loadAdvancedConfig().

◆ txtSuspExt

Gtk::Entry* SettingsPage::txtSuspExt = nullptr
private

Definition at line 157 of file SettingsPage.hpp.

Referenced by build_antiransom_advanced_tab(), and loadAdvancedConfig().

◆ updatingToggle

bool SettingsPage::updatingToggle = false
private

Definition at line 227 of file SettingsPage.hpp.

Referenced by SettingsPage().

◆ whitelistSelection

Glib::RefPtr<Gtk::SingleSelection> SettingsPage::whitelistSelection
private

Definition at line 131 of file SettingsPage.hpp.

◆ whitelistStore

Glib::RefPtr<Gtk::StringList> SettingsPage::whitelistStore
private

Definition at line 132 of file SettingsPage.hpp.

◆ whitelistView

Gtk::ListView SettingsPage::whitelistView
private

Definition at line 133 of file SettingsPage.hpp.


The documentation for this class was generated from the following files: