/*
* BastionGuard™
* Copyright (C) 2025–2026 Calogero Scarnà
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* BastionGuard™ is a trademark of Calogero Scarnà.
* The BastionGuard™ name and branding are not licensed under the GPL.
*/
#include "Resource.hpp"
#include "ClamdConfig.hpp"
#include
#include
#include
#include
#include
#include
#include
using namespace std;
bool ClamdConfig::load(const std::string& path) {
rawLines.clear();
options.clear();
ifstream file(path);
if (!file.is_open()) return false;
string line;
while (getline(file, line)) {
Line ln;
ln.text = line;
string trimmed = line;
bool commented = false;
if (!trimmed.empty() && trimmed[0] == '#') {
commented = true;
trimmed = trimmed.substr(1);
}
istringstream iss(trimmed);
string key, value;
if (iss >> key >> value) {
ln.key = key;
ln.value = value;
ln.commented = commented;
if (!commented) {
options[key] = value;
}
}
rawLines.push_back(ln);
}
return true;
}
bool ClamdConfig::save(const std::string& path) {
ofstream file(path);
if (!file.is_open()) return false;
for (auto& ln : rawLines) {
if (!ln.key.empty()) {
// aggiorna il valore
auto it = options.find(ln.key);
if (it != options.end()) {
if (ln.commented) {
file << "#";
}
file << ln.key << " " << it->second << "\n";
continue;
}
}
file << ln.text << "\n";
}
return true;
}
bool ClamdConfig::backupFile(const std::string& path) const {
try {
std::filesystem::path p(path);
if (std::filesystem::exists(p)) {
auto backup = p;
backup += ".bak";
std::filesystem::copy_file(p, backup,
std::filesystem::copy_options::overwrite_existing);
}
return true;
} catch (std::exception& e) {
std::cerr << _("❌ Errore backup: ") << e.what() << std::endl;
return false;
}
}
bool ClamdConfig::saveWithBackup(const std::string& path) {
if (!backupFile(path)) {
std::cerr << _("❌ Impossibile creare il backup di ") << path << std::endl;
return false;
}
return save(path);
}
void ClamdConfig::setOption(const std::string& key, const std::string& value) {
options[key] = value;
}
std::string ClamdConfig::getOption(const std::string& key) const {
auto it = options.find(key);
return (it != options.end()) ? it->second : "";
}
bool ClamdConfig::getOptionBool(const std::string& key) const {
auto it = options.find(key);
if (it == options.end()) return false;
return isYes(it->second);
}
void ClamdConfig::setOptionBool(const std::string& key, bool enabled) {
options[key] = enabled ? "yes" : "no";
}
std::vector ClamdConfig::getOnAccessPaths() const {
std::vector paths;
for (auto& ln : rawLines) {
if (!ln.commented && ln.key == "OnAccessIncludePath") {
paths.push_back(ln.value);
}
}
return paths;
}
void ClamdConfig::addOnAccessPath(const std::string& path) {
Line ln;
ln.key = "OnAccessIncludePath";
ln.value = path;
ln.text = ln.key + " " + ln.value;
ln.commented = false;
rawLines.push_back(ln);
options[ln.key] = ln.value;
}
void ClamdConfig::removeOnAccessPath(const std::string& path) {
rawLines.erase(std::remove_if(rawLines.begin(), rawLines.end(),
[&](const Line& ln) {
return ln.key == "OnAccessIncludePath" && ln.value == path;
}),
rawLines.end());
}
std::map ClamdConfig::getScanOptions() const {
std::map scanOpts;
for (auto& ln : rawLines) {
if (!ln.key.empty()) {
// Consideriamo solo quelli che hanno valore yes/no
if (ln.value == "yes" || ln.value == "no") {
scanOpts[ln.key] = !ln.commented && isYes(ln.value);
}
}
}
return scanOpts;
}
void ClamdConfig::setScanOption(const std::string& key, bool enabled) {
options[key] = enabled ? "yes" : "no";
for (auto& ln : rawLines) {
if (ln.key == key) {
ln.value = enabled ? "yes" : "no";
ln.text = (ln.commented ? "#" : "") + ln.key + " " + ln.value;
}
}
}
bool ClamdConfig::isYes(const std::string& v) {
std::string val = v;
std::transform(val.begin(), val.end(), val.begin(), ::tolower);
return (val == "yes" || val == "true" || val == "1");
}