#include <optional>
#include <span>
#include <string_view>
#include <utility>
#include "cow_string.hpp"
#include "object.hpp"
#include "transformer/base.hpp"
#include "transformer/base64_decode.hpp"
#include "transformer/base64_encode.hpp"
#include "transformer/compress_whitespace.hpp"
#include "transformer/css_decode.hpp"
#include "transformer/html_entity_decode.hpp"
#include "transformer/js_decode.hpp"
#include "transformer/lowercase.hpp"
#include "transformer/manager.hpp"
#include "transformer/normalize_path.hpp"
#include "transformer/remove_comments.hpp"
#include "transformer/remove_nulls.hpp"
#include "transformer/shell_unescape.hpp"
#include "transformer/unicode_normalize.hpp"
#include "transformer/url_basename.hpp"
#include "transformer/url_decode.hpp"
#include "transformer/url_path.hpp"
#include "transformer/url_querystring.hpp"
namespace ddwaf::transformer {
namespace {
bool call_transformer(transformer_id id, cow_string &str)
{
switch (id) {
case transformer_id::lowercase:
return lowercase::transform(str);
case transformer_id::remove_nulls:
return remove_nulls::transform(str);
case transformer_id::compress_whitespace:
return compress_whitespace::transform(str);
case transformer_id::normalize_path:
return normalize_path::transform(str);
case transformer_id::normalize_path_win:
return normalize_path_win::transform(str);
case transformer_id::unicode_normalize:
return unicode_normalize::transform(str);
case transformer_id::remove_comments:
return remove_comments::transform(str);
case transformer_id::url_decode:
return url_decode::transform(str);
case transformer_id::url_decode_iis:
return url_decode_iis::transform(str);
case transformer_id::url_basename:
return url_basename::transform(str);
case transformer_id::url_path:
return url_path::transform(str);
case transformer_id::url_querystring:
return url_querystring::transform(str);
case transformer_id::shell_unescape:
return shell_unescape::transform(str);
case transformer_id::css_decode:
return css_decode::transform(str);
case transformer_id::js_decode:
return js_decode::transform(str);
case transformer_id::html_entity_decode:
return html_entity_decode::transform(str);
case transformer_id::base64_decode:
return base64_decode::transform(str);
case transformer_id::base64url_decode:
return base64url_decode::transform(str);
case transformer_id::base64_encode:
return base64_encode::transform(str);
}
return false;
}
}
std::optional<cow_string> manager::transform(
object_view source, const std::span<const transformer_id> &transformers)
{
if (!source.is_string() || source.empty()) {
return std::nullopt;
}
bool transformed = false;
cow_string str(source.as<std::string_view>());
for (auto transformer : transformers) {
auto res = call_transformer(transformer, str);
transformed = transformed || res;
}
if (!transformed) {
return std::nullopt;
}
return {std::move(str)};
}
}