189 lines
5.3 KiB
C++
189 lines
5.3 KiB
C++
/*
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
*
|
|
* 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 <fstream>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <filesystem>
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
#include <glib/gi18n.h>
|
|
|
|
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<std::string> ClamdConfig::getOnAccessPaths() const {
|
|
std::vector<std::string> 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<std::string, bool> ClamdConfig::getScanOptions() const {
|
|
std::map<std::string, bool> 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");
|
|
}
|