64static bool icontains(std::string hay, std::string needle) {
65 auto tolower_ascii = [](
unsigned char c){
return (c >=
'A' && c <=
'Z') ? char(c + 32) : char(c); };
66 for (
auto& c : hay) c = tolower_ascii((
unsigned char)c);
67 for (
auto& c : needle) c = tolower_ascii((
unsigned char)c);
68 return hay.find(needle) != std::string::npos;
93 namespace fs = std::filesystem;
96 if (fs::exists(lang_conf_path, ec) && !ec) {
100 std::string cfgdir = Glib::get_home_dir() +
"/.config/BastionGuard";
103 std::ofstream out(lang_conf_path, std::ios::out | std::ios::trunc);
104 if (!out.is_open()) {
105 std::cerr <<
"[Lang] ⚠️ Impossibile creare " << lang_conf_path << std::endl;
109 out <<
"LANG=en_US.UTF-8\n";
110 out <<
"LC_ALL=en_US.UTF-8\n";
111 out <<
"LANGUAGE=en_US\n";
114 std::cout <<
"[Lang] ✅ Creato lang.conf di default: " << lang_conf_path << std::endl;
141 const char* homeC = std::getenv(
"HOME");
143 std::cerr <<
_(
"[Main] ⚠️ HOME non trovato, salto install wrapper") <<
"\n";
147 std::string home = homeC;
148 std::string localBin = home +
"/.local/bin";
149 std::string targetLink = localBin +
"/xdg-open";
150 std::string realApp =
"/usr/bin/BastionGuard-bankopener";
155 fs::create_directories(localBin, ec);
157 std::cerr << Glib::ustring::compose(
158 _(
"[Main] ⚠️ Errore creando %1: %2"), localBin, ec.message()) <<
"\n";
163 bool must_create =
true;
164 if (fs::exists(targetLink)) {
166 fs::file_status st = fs::symlink_status(targetLink, ec2);
167 if (!ec2 && fs::is_symlink(st)) {
169 std::string dest = fs::read_symlink(targetLink).string();
170 if (dest == realApp) must_create =
false;
175 try { fs::remove(targetLink); }
catch (...) {}
182 if (fs::exists(targetLink)) fs::remove(targetLink);
183 fs::create_symlink(realApp, targetLink);
184 std::cout << Glib::ustring::compose(
185 _(
"[Main] 🔗 Creato symlink: %1 → %2"), targetLink, realApp) <<
"\n";
186 }
catch (
const std::exception& e) {
187 std::cerr << Glib::ustring::compose(
188 _(
"[Main] ⚠️ Impossibile creare symlink %1: %2"), targetLink, e.what()) <<
"\n";
191 std::cout << Glib::ustring::compose(
192 _(
"[Main] 🔁 Symlink già presente: %1 → %2"), targetLink, realApp) <<
"\n";
196 std::map<std::string, std::string> rc_to_line;
197 rc_to_line[home +
"/.bashrc"] =
"export PATH=\"$HOME/.local/bin:$PATH\"";
198 rc_to_line[home +
"/.zshrc"] =
"export PATH=\"$HOME/.local/bin:$PATH\"";
199 rc_to_line[home +
"/.config/fish/config.fish"] =
"set -gx PATH $HOME/.local/bin $PATH";
200 rc_to_line[home +
"/.cshrc"] =
"setenv PATH $HOME/.local/bin:$PATH";
201 rc_to_line[home +
"/.tcshrc"] =
"setenv PATH $HOME/.local/bin:$PATH";
203 for (
const auto& [rcfile, line] : rc_to_line) {
204 bool present =
false;
205 std::ifstream in(rcfile);
208 while (std::getline(in, l)) {
209 if (l.find(line) != std::string::npos) { present =
true;
break; }
215 std::ofstream out(rcfile, std::ios::app);
217 out <<
"\n# Added by BastionGuard Secure Browser\n" << line <<
"\n";
218 std::cout << Glib::ustring::compose(
219 _(
"[Main] ⚙️ Aggiornato %1"), rcfile) <<
"\n";
224 const char* oldPathC = std::getenv(
"PATH");
225 std::string oldPath = oldPathC ? oldPathC :
"";
226 std::string newPath = localBin +
":" + oldPath;
227 setenv(
"PATH", newPath.c_str(), 1);
229 std::cout <<
_(
"[Main] ✅ PATH aggiornato per sessione corrente") <<
"\n";
231 }
catch (
const std::exception& ex) {
232 std::cerr << Glib::ustring::compose(
233 _(
"[Main] ⚠️ Errore ensureUserWrapperInstalled(): %1"), ex.what()) <<
"\n";
413int main(
int argc,
char *argv[]) {
415 std::string lang_conf = Glib::get_home_dir() +
"/.config/BastionGuard/lang.conf";
418 std::ifstream f(lang_conf);
421 while (std::getline(f, line)) {
422 auto pos = line.find(
'=');
423 if (pos != std::string::npos) {
424 std::string key = line.substr(0, pos);
425 std::string val = line.substr(pos + 1);
426 if (!key.empty() && !val.empty()) {
427 setenv(key.c_str(), val.c_str(), 1);
432 std::cout <<
"[Lang] Config caricata da " << lang_conf << std::endl;
434 std::cerr <<
"[Lang] ⚠️ Impossibile aprire lang.conf, forzo inglese di default" << std::endl;
438 const char* lang_env = std::getenv(
"LANG");
439 if (!lang_env || std::string(lang_env).empty()) {
440 setenv(
"LANG",
"en_US.UTF-8", 1);
443 const char* lc_all_env = std::getenv(
"LC_ALL");
444 if (!lc_all_env || std::string(lc_all_env).empty()) {
445 setenv(
"LC_ALL",
"en_US.UTF-8", 1);
448 const char* language_env = std::getenv(
"LANGUAGE");
449 if (!language_env || std::string(language_env).empty()) {
450 setenv(
"LANGUAGE",
"en_US", 1);
453 const char* applied = setlocale(LC_ALL,
"");
455 applied = setlocale(LC_ALL,
"en_US.UTF-8");
458 applied = setlocale(LC_ALL,
"en_US");
461 applied = setlocale(LC_ALL,
"C.UTF-8");
464 applied = setlocale(LC_ALL,
"C");
467 bindtextdomain(
"BastionGuard",
LOCALEDIR);
468 bind_textdomain_codeset(
"BastionGuard",
"UTF-8");
469 textdomain(
"BastionGuard");
471 bool do_update_phish =
false;
472 bool do_update_sanesecurity =
false;
473 bool start_minimized =
false;
475 std::vector<char*> gtk_argv;
476 gtk_argv.push_back(argv[0]);
478 for (
int i = 1; i < argc; ++i) {
479 std::string arg = argv[i];
480 if (arg ==
"--update-phish") {
481 do_update_phish =
true;
482 }
else if (arg ==
"--update-sanesecurity") {
483 do_update_sanesecurity =
true;
484 }
else if (arg ==
"--minimized") {
485 start_minimized =
true;
487 gtk_argv.push_back(argv[i]);
493 if (do_update_phish) {
494 std::cout <<
"[BastionGuard] " <<
_(
"Avvio aggiornamento blacklist (modalità headless)...") << std::endl;
498 std::cout <<
"[BastionGuard] " <<
_(
"✔ Blacklist aggiornata con successo.") << std::endl;
501 std::cerr <<
"[BastionGuard] " <<
_(
"❌ Errore durante l'aggiornamento blacklist.") << std::endl;
504 }
catch (
const std::exception& ex) {
505 std::cerr <<
"[BastionGuard] " <<
_(
"Eccezione durante updatePhishLists(): ") << ex.what() << std::endl;
510 if (do_update_sanesecurity) {
511 std::cout <<
_(
"[BastionGuard] Avvio aggiornamento SaneSecurity (modalità headless)...") << std::endl;
515 std::cout <<
_(
"[BastionGuard] ✔ Aggiornamento SaneSecurity completato.") << std::endl;
518 std::cerr <<
_(
"[BastionGuard] ❌ Errore durante l'aggiornamento SaneSecurity.") << std::endl;
521 }
catch (
const std::exception& ex) {
522 std::cerr <<
_(
"[BastionGuard] ❌ Eccezione durante updateSaneSecurity(): ")
523 << ex.what() << std::endl;
529 struct passwd* pw = getpwnam(
"clamav");
531 std::cerr <<
_(
"[Main] ❌ Utente 'clamav' non trovato. Lo scanner userà l'utente normale.") << std::endl;
533 uid_t original_euid = geteuid();
534 gid_t original_egid = getegid();
536 setenv(
"BastionGuard_ORIG_EUID", std::to_string(original_euid).c_str(), 1);
537 setenv(
"BastionGuard_ORIG_EGID", std::to_string(original_egid).c_str(), 1);
539 initgroups(
"clamav", pw->pw_gid);
541 if (setegid(pw->pw_gid) != 0)
542 perror(
"[Main] setegid clamav");
544 if (seteuid(pw->pw_uid) != 0)
545 perror(
"[Main] seteuid clamav");
547 std::cout <<
_(
"[Main] 🔐 Processo configurato per lanciare i sottoprocessi come 'clamav'") << std::endl;
549 setegid(original_egid);
550 seteuid(original_euid);
554 int gtk_argc =
static_cast<int>(gtk_argv.size());
555 char** gtk_argv_data = gtk_argv.data();
557 auto app = Glib::make_refptr_for_instance<ClamApp>(
new ClamApp(start_minimized));
558 return app->run(gtk_argc, gtk_argv_data);
void open_settings_window()
static void ensure_dir_exists(const std::string &dir)
static void ensure_lang_conf_exists(const std::string &lang_conf_path)
static std::string getenv_str(const char *k)
static void ensureUserWrapperInstalled()
static bool icontains(std::string hay, std::string needle)
static bool wizard_needed()
static std::string resolve_path(const std::string &local, const std::string &installed)
static bool should_enable_trayicon()