Add 'mode' argument for match, regex and cidr_match

This commit is contained in:
Gunnar Beutner 2017-05-15 16:02:20 +02:00
parent dc9f129060
commit 958d3982c5
3 changed files with 145 additions and 17 deletions

View File

@ -16,7 +16,10 @@ Signature:
function regex(pattern, text)
Returns true if the regular expression matches the text, false otherwise.
Returns true if the regular expression matches the text, false otherwise. The mode argument is
optional and can be either MatchAll (in which case all elements for an array have to match) or MatchAny
(in which case at least one element has to match). The default mode is MatchAll.
**Tip**: In case you are looking for regular expression tests try [regex101](https://regex101.com).
Example:
@ -34,9 +37,11 @@ Example:
Signature:
function match(pattern, text)
function match(pattern, text, mode)
Returns true if the wildcard (`?*`) pattern matches the text, false otherwise.
Returns true if the wildcard (`?*`) pattern matches the text, false otherwise. The mode argument is
optional and can be either MatchAll (in which case all elements for an array have to match) or MatchAny
(in which case at least one element has to match). The default mode is MatchAll.
Example:
@ -59,7 +64,10 @@ Signature:
Returns true if the CIDR pattern matches the IP address, false otherwise.
IPv4 addresses are converted to IPv4-mapped IPv6 addresses before being
matched against the pattern.
matched against the pattern. The mode argument is optional and can be
either MatchAll (in which case all elements for an array have to match) or MatchAny
(in which case at least one element has to match). The default mode is MatchAll.
Example:

View File

@ -27,6 +27,7 @@
#include "base/configtype.hpp"
#include "base/application.hpp"
#include "base/dependencygraph.hpp"
#include "base/initialize.hpp"
#include <boost/regex.hpp>
#include <algorithm>
#include <set>
@ -36,9 +37,9 @@
using namespace icinga;
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, regex, &ScriptUtils::Regex, "pattern:text");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, match, &Utility::Match, "pattern:text");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, cidr_match, &Utility::CidrMatch, "pattern:ip");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, regex, &ScriptUtils::Regex, "pattern:text:mode");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, match, &ScriptUtils::Match, "pattern:text:mode");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, cidr_match, &ScriptUtils::CidrMatch, "pattern:ip:mode");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, len, &ScriptUtils::Len, "value");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, union, &ScriptUtils::Union, "");
REGISTER_SAFE_SCRIPTFUNCTION_NS(System, intersection, &ScriptUtils::Intersection, "");
@ -67,6 +68,20 @@ REGISTER_SAFE_SCRIPTFUNCTION_NS(System, escape_create_process_arg, &Utility::Esc
REGISTER_SCRIPTFUNCTION_NS(System, ptr, &ScriptUtils::Ptr, "object");
REGISTER_SCRIPTFUNCTION_NS(System, sleep, &Utility::Sleep, "interval");
INITIALIZE_ONCE(&ScriptUtils::StaticInitialize);
enum MatchType
{
MatchAll,
MatchAny
};
void ScriptUtils::StaticInitialize(void)
{
ScriptGlobal::Set("MatchAll", MatchAll);
ScriptGlobal::Set("MatchAny", MatchAny);
}
String ScriptUtils::CastString(const Value& value)
{
return value;
@ -81,18 +96,120 @@ bool ScriptUtils::CastBool(const Value& value)
{
return value.ToBool();
}
bool ScriptUtils::Regex(const String& pattern, const String& text)
bool ScriptUtils::Regex(const std::vector<Value>& args)
{
bool res = false;
try {
boost::regex expr(pattern.GetData());
boost::smatch what;
res = boost::regex_search(text.GetData(), what, expr);
} catch (boost::exception&) {
res = false; /* exception means something went terribly wrong */
if (args.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Regular expression and text must be specified."));
Array::Ptr texts = new Array();
String pattern = args[0];
Value argTexts = args[1];
MatchType mode;
if (args.size() > 2)
mode = static_cast<MatchType>(static_cast<int>(args[2]));
else
mode = MatchAll;
if (argTexts.IsObjectType<Array>())
texts = argTexts;
else {
texts = new Array();
texts->Add(argTexts);
}
return res;
ObjectLock olock(texts);
for (const String& text : texts) {
bool res = false;
try {
boost::regex expr(pattern.GetData());
boost::smatch what;
res = boost::regex_search(text.GetData(), what, expr);
} catch (boost::exception&) {
res = false; /* exception means something went terribly wrong */
}
if (mode == MatchAny && res)
return true;
else if (mode == MatchAll && !res)
return false;
}
return mode == MatchAll;
}
bool ScriptUtils::Match(const std::vector<Value>& args)
{
if (args.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Pattern and text must be specified."));
Array::Ptr texts = new Array();
String pattern = args[0];
Value argTexts = args[1];
MatchType mode;
if (args.size() > 2)
mode = static_cast<MatchType>(static_cast<int>(args[2]));
else
mode = MatchAll;
if (argTexts.IsObjectType<Array>())
texts = argTexts;
else {
texts = new Array();
texts->Add(argTexts);
}
ObjectLock olock(texts);
for (const String& text : texts) {
bool res = Utility::Match(pattern, text);
if (mode == MatchAny && res)
return true;
else if (mode == MatchAll && !res)
return false;
}
return mode == MatchAll;
}
bool ScriptUtils::CidrMatch(const std::vector<Value>& args)
{
if (args.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("CIDR and IP address must be specified."));
Array::Ptr ips = new Array();
String pattern = args[0];
Value argIps = args[1];
MatchType mode;
if (args.size() > 2)
mode = static_cast<MatchType>(static_cast<int>(args[2]));
else
mode = MatchAll;
if (argIps.IsObjectType<Array>())
ips = argIps;
else {
ips = new Array();
ips->Add(argIps);
}
ObjectLock olock(ips);
for (const String& ip : ips) {
bool res = Utility::CidrMatch(pattern, ip);
if (mode == MatchAny && res)
return true;
else if (mode == MatchAll && !res)
return false;
}
return mode == MatchAll;
}
double ScriptUtils::Len(const Value& value)

View File

@ -36,10 +36,13 @@ namespace icinga
class I2_BASE_API ScriptUtils
{
public:
static void StaticInitialize(void);
static String CastString(const Value& value);
static double CastNumber(const Value& value);
static bool CastBool(const Value& value);
static bool Regex(const String& pattern, const String& text);
static bool Regex(const std::vector<Value>& args);
static bool Match(const std::vector<Value>& args);
static bool CidrMatch(const std::vector<Value>& args);
static double Len(const Value& value);
static Array::Ptr Union(const std::vector<Value>& arguments);
static Array::Ptr Intersection(const std::vector<Value>& arguments);