| /* @file |
| |
| Implementation for creating all values. |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| #include "tsutil/DbgCtl.h" |
| #include <string> |
| #include <algorithm> |
| |
| #include "matcher.h" |
| |
| namespace header_rewrite_ns |
| { |
| const char PLUGIN_NAME[] = "header_rewrite"; |
| const char PLUGIN_NAME_DBG[] = "dbg_header_rewrite"; |
| |
| DbgCtl dbg_ctl{PLUGIN_NAME_DBG}; |
| DbgCtl pi_dbg_ctl{PLUGIN_NAME}; |
| } // namespace header_rewrite_ns |
| |
| static bool |
| match_with_modifiers(std::string_view rhs, std::string_view lhs, CondModifiers mods) |
| { |
| // Case-aware equality |
| static auto equals = [](std::string_view a, std::string_view b, CondModifiers mods) -> bool { |
| if (has_modifier(mods, CondModifiers::MOD_NOCASE)) { |
| return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), [](char c1, char c2) { |
| return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2)); |
| }); |
| } |
| return a == b; |
| }; |
| |
| // Case-aware substring search |
| static auto contains = [](std::string_view haystack, std::string_view needle, CondModifiers mods) -> bool { |
| if (!has_modifier(mods, CondModifiers::MOD_NOCASE)) { |
| return haystack.find(needle) != std::string_view::npos; |
| } |
| auto it = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { |
| return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2)); |
| }); |
| return it != haystack.end(); |
| }; |
| |
| if (has_modifier(mods, CondModifiers::MOD_EXT)) { |
| auto dot = rhs.rfind('.'); |
| return dot != std::string_view::npos && dot + 1 < rhs.size() && equals(rhs.substr(dot + 1), lhs, mods); |
| } |
| |
| if (has_modifier(mods, CondModifiers::MOD_SUF)) { |
| return rhs.size() >= lhs.size() && equals(rhs.substr(rhs.size() - lhs.size()), lhs, mods); |
| } |
| |
| if (has_modifier(mods, CondModifiers::MOD_PRE)) { |
| return rhs.size() >= lhs.size() && equals(rhs.substr(0, lhs.size()), lhs, mods); |
| } |
| |
| if (has_modifier(mods, CondModifiers::MOD_MID)) { |
| return contains(rhs, lhs, mods); |
| } |
| |
| return equals(rhs, lhs, mods); |
| } |
| |
| // Special case for strings, to allow for insensitive case comparisons for std::string matchers. |
| template <> |
| bool |
| Matchers<std::string>::test_eq(const std::string &t) const |
| { |
| std::string_view lhs = std::get<std::string>(_data); |
| std::string_view rhs = t; |
| bool result = match_with_modifiers(rhs, lhs, _mods); |
| |
| if (pi_dbg_ctl.on()) { |
| debug_helper(t, " == ", result); |
| } |
| |
| return result; |
| } |
| |
| template <> |
| bool |
| Matchers<std::string>::test_set(const std::string &t) const |
| { |
| TSAssert(std::holds_alternative<std::set<std::string>>(_data)); |
| std::string_view rhs = t; |
| |
| for (const auto &entry : std::get<std::set<std::string>>(_data)) { |
| if (match_with_modifiers(rhs, entry, _mods)) { |
| if (pi_dbg_ctl.on()) { |
| debug_helper(t, " ∈ ", true); |
| } |
| return true; |
| } |
| } |
| |
| debug_helper(t, " ∈ ", false); |
| return false; |
| } |
| |
| template <> |
| bool |
| Matchers<const sockaddr *>::test(const sockaddr *const &addr, const Resources & /* Not used */) const |
| { |
| TSAssert(std::holds_alternative<swoc::IPRangeSet>(_data)); |
| const auto &ranges = std::get<swoc::IPRangeSet>(_data); |
| |
| if (ranges.contains(swoc::IPAddr(addr))) { |
| if (pi_dbg_ctl.on()) { |
| char text[INET6_ADDRSTRLEN]; |
| Dbg(pi_dbg_ctl, "Successfully found IP-range match on %s", getIP(addr, text)); |
| } |
| return true; |
| } |
| |
| return false; |
| } |