#pragma once
#include "configuration/common/configuration.hpp"
#include "obfuscator.hpp"
#include "rule.hpp"
#include "scanner.hpp"
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace ddwaf {
class configuration_collector {
public:
configuration_collector(configuration_change_spec &change, configuration_spec &config)
: change_(change), config_(config){};
configuration_collector(const configuration_collector &) = delete;
configuration_collector &operator=(const configuration_collector &) = delete;
configuration_collector(configuration_collector &&) = delete;
configuration_collector &operator=(configuration_collector &&) = delete;
~configuration_collector() = default;
[[nodiscard]] bool contains_rule(const std::string &id) const
{
return config_.base_rules.contains(id) || config_.user_rules.contains(id);
}
[[nodiscard]] bool contains_filter(const std::string &id) const
{
return config_.rule_filters.contains(id) || config_.input_filters.contains(id);
}
[[nodiscard]] bool contains_processor(const std::string &id) const
{
return config_.processors.contains(id);
}
[[nodiscard]] bool contains_scanner(const std::string &id) const
{
return config_.scanners.contains(id);
}
[[nodiscard]] bool contains_action(const std::string &id) const
{
return config_.actions.contains(id);
}
[[nodiscard]] bool contains_obfuscator() const { return config_.obfuscator != nullptr; }
void emplace_rule(std::string id, rule_spec spec)
{
if (spec.source == core_rule::source_type::base) {
change_.content |= change_set::rules;
change_.base_rules.emplace(id);
config_.base_rules.emplace(std::move(id), std::move(spec));
} else {
change_.content |= change_set::custom_rules;
change_.user_rules.emplace(id);
config_.user_rules.emplace(std::move(id), std::move(spec));
}
}
void emplace_rule_override(std::string id, rule_override_spec spec)
{
change_.content |= change_set::rule_overrides;
if (spec.type == reference_type::id) {
change_.rule_overrides_by_id.emplace(id);
config_.rule_overrides_by_id.emplace(std::move(id), std::move(spec));
} else if (spec.type == reference_type::tags) {
change_.rule_overrides_by_tags.emplace(id);
config_.rule_overrides_by_tags.emplace(std::move(id), std::move(spec));
}
}
void emplace_filter(std::string id, rule_filter_spec spec)
{
change_.content |= change_set::filters;
change_.rule_filters.emplace(id);
config_.rule_filters.emplace(std::move(id), std::move(spec));
}
void emplace_filter(std::string id, input_filter_spec spec)
{
change_.content |= change_set::filters;
change_.input_filters.emplace(id);
config_.input_filters.emplace(std::move(id), std::move(spec));
}
void emplace_processor(std::string id, processor_spec spec)
{
change_.content |= change_set::processors;
change_.processors.emplace(id);
config_.processors.emplace(std::move(id), std::move(spec));
}
void emplace_processor_override(std::string id, processor_override_spec spec)
{
change_.content |= change_set::processor_overrides;
change_.processor_overrides.emplace(id);
config_.processor_overrides.emplace(std::move(id), std::move(spec));
}
void emplace_scanner(std::string id, scanner scnr)
{
change_.content |= change_set::scanners;
change_.scanners.emplace(id);
config_.scanners.emplace(std::move(id), std::move(scnr));
}
void emplace_action(std::string id, action_spec spec)
{
change_.content |= change_set::actions;
change_.actions.emplace(id);
config_.actions.emplace(std::move(id), std::move(spec));
}
void emplace_rule_data(std::string data_id, std::string id, data_type type,
std::vector<data_spec::value_type> values)
{
change_.content |= change_set::rule_data;
auto it = config_.rule_data.find(data_id);
if (it == config_.rule_data.end()) {
auto &spec = config_.rule_data[data_id];
spec.type = type;
spec.values.emplace(id, std::move(values));
} else {
it->second.values.emplace(id, std::move(values));
}
change_.rule_data.emplace_back(std::move(data_id), std::move(id));
}
void emplace_exclusion_data(std::string data_id, std::string id, data_type type,
std::vector<data_spec::value_type> values)
{
change_.content |= change_set::exclusion_data;
auto it = config_.exclusion_data.find(data_id);
if (it == config_.exclusion_data.end()) {
auto &spec = config_.exclusion_data[data_id];
spec.type = type;
spec.values.emplace(id, std::move(values));
} else {
it->second.values.emplace(id, std::move(values));
}
change_.exclusion_data.emplace_back(std::move(data_id), std::move(id));
}
void set_obfuscator(std::unique_ptr<match_obfuscator> &&obfuscator)
{
change_.content |= change_set::obfuscator;
config_.obfuscator = std::move(obfuscator);
}
protected:
configuration_change_spec &change_;
configuration_spec &config_;
};
}