diff --git a/lib/config/applyrule.hpp b/lib/config/applyrule.hpp index 40251a4a8..cf9b6e5e6 100644 --- a/lib/config/applyrule.hpp +++ b/lib/config/applyrule.hpp @@ -82,6 +82,8 @@ public: static const std::vector& GetRules(const Type::Ptr& sourceType, const Type::Ptr& targetType); static const std::set& GetTargetedHostRules(const Type::Ptr& sourceType, const String& host); static const std::set& GetTargetedServiceRules(const Type::Ptr& sourceType, const String& host, const String& service); + static bool GetTargetHosts(Expression* assignFilter, std::vector& hosts, const Dictionary::Ptr& constants = nullptr); + static bool GetTargetServices(Expression* assignFilter, std::vector>& services, const Dictionary::Ptr& constants = nullptr); static void RegisterType(const String& sourceType, const std::vector& targetTypes); static bool IsValidSourceType(const String& sourceType); @@ -108,8 +110,6 @@ private: static RuleMap m_Rules; static bool AddTargetedRule(const ApplyRule::Ptr& rule, const String& targetType, PerSourceType& rules); - static bool GetTargetHosts(Expression* assignFilter, std::vector& hosts, const Dictionary::Ptr& constants = nullptr); - static bool GetTargetServices(Expression* assignFilter, std::vector>& services, const Dictionary::Ptr& constants = nullptr); static std::pair GetTargetService(Expression* assignFilter, const Dictionary::Ptr& constants); static const String * GetComparedName(Expression* assignFilter, const char * lcType, const Dictionary::Ptr& constants); static bool IsNameIndexer(Expression* exp, const char * lcType, const Dictionary::Ptr& constants); diff --git a/lib/remote/filterutility.cpp b/lib/remote/filterutility.cpp index 57564e954..468b91e0e 100644 --- a/lib/remote/filterutility.cpp +++ b/lib/remote/filterutility.cpp @@ -2,6 +2,7 @@ #include "remote/filterutility.hpp" #include "remote/httputility.hpp" +#include "config/applyrule.hpp" #include "config/configcompiler.hpp" #include "config/expression.hpp" #include "base/namespace.hpp" @@ -271,18 +272,73 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c if (query->Contains("filter")) { String filter = HttpUtility::GetLastParameter(query, "filter"); std::unique_ptr ufilter = ConfigCompiler::CompileText("", filter); - Dictionary::Ptr filter_vars = query->Get("filter_vars"); - if (filter_vars) { - ObjectLock olock(filter_vars); - for (const Dictionary::Pair& kv : filter_vars) { - frameNS->Set(kv.first, kv.second); + bool targeted = false; + std::vector targets; + + if (dynamic_cast(provider.get())) { + auto dict (dynamic_cast(ufilter.get())); + + if (dict) { + auto& subex (dict->GetExpressions()); + + if (subex.size() == 1u) { + if (type == "Host") { + std::vector targetNames; + + if (ApplyRule::GetTargetHosts(subex.at(0).get(), targetNames, filter_vars)) { + static const auto typeHost (Type::GetByName("Host")); + static const auto ctypeHost (dynamic_cast(typeHost.get())); + targeted = true; + + for (auto name : targetNames) { + auto target (ctypeHost->GetObject(*name)); + + if (target) { + targets.emplace_back(target); + } + } + } + } else if (type == "Service") { + std::vector> targetNames; + + if (ApplyRule::GetTargetServices(subex.at(0).get(), targetNames, filter_vars)) { + static const auto typeService (Type::GetByName("Service")); + static const auto ctypeService (dynamic_cast(typeService.get())); + targeted = true; + + for (auto name : targetNames) { + auto target (ctypeService->GetObject(*name.first + "!" + *name.second)); + + if (target) { + targets.emplace_back(target); + } + } + } + } + } } } - provider->FindTargets(type, [&permissionFrame, &permissionFilter, &frame, &ufilter, &result, variableName](const Object::Ptr& target) { - FilteredAddTarget(permissionFrame, permissionFilter.get(), frame, &*ufilter, result, variableName, target); - }); + if (targeted) { + for (auto& target : targets) { + if (FilterUtility::EvaluateFilter(permissionFrame, permissionFilter.get(), target, variableName)) { + result.emplace_back(std::move(target)); + } + } + } else { + if (filter_vars) { + ObjectLock olock (filter_vars); + + for (auto& kv : filter_vars) { + frameNS->Set(kv.first, kv.second); + } + } + + provider->FindTargets(type, [&permissionFrame, &permissionFilter, &frame, &ufilter, &result, variableName](const Object::Ptr& target) { + FilteredAddTarget(permissionFrame, permissionFilter.get(), frame, &*ufilter, result, variableName, target); + }); + } } else { /* Ensure to pass a nullptr as filter expression. * GCC 8.1.1 on F28 causes problems, see GH #6533.