]> granicus.if.org Git - icinga2/blob - lib/livestatus/attributefilter.cpp
Docs: Explain across midnight time periods with an overlapping range
[icinga2] / lib / livestatus / attributefilter.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "livestatus/attributefilter.hpp"
4 #include "base/convert.hpp"
5 #include "base/array.hpp"
6 #include "base/objectlock.hpp"
7 #include "base/logger.hpp"
8 #include <boost/regex.hpp>
9 #include <boost/algorithm/string/predicate.hpp>
10
11 using namespace icinga;
12
13 AttributeFilter::AttributeFilter(String column, String op, String operand)
14         : m_Column(std::move(column)), m_Operator(std::move(op)), m_Operand(std::move(operand))
15 { }
16
17 bool AttributeFilter::Apply(const Table::Ptr& table, const Value& row)
18 {
19         Column column = table->GetColumn(m_Column);
20
21         Value value = column.ExtractValue(row);
22
23         if (value.IsObjectType<Array>()) {
24                 Array::Ptr array = value;
25
26                 if (m_Operator == ">=" || m_Operator == "<") {
27                         bool negate = (m_Operator == "<");
28
29                         ObjectLock olock(array);
30                         for (const String& item : array) {
31                                 if (item == m_Operand)
32                                         return !negate; /* Item found in list. */
33                         }
34
35                         return negate; /* Item not found in list. */
36                 } else if (m_Operator == "=") {
37                         return (array->GetLength() == 0);
38                 } else {
39                         BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid operator for column '" + m_Column + "': " + m_Operator + " (expected '>=' or '=')."));
40                 }
41         } else {
42                 if (m_Operator == "=") {
43                         if (value.GetType() == ValueNumber || value.GetType() == ValueBoolean)
44                                 return (static_cast<double>(value) == Convert::ToDouble(m_Operand));
45                         else
46                                 return (static_cast<String>(value) == m_Operand);
47                 } else if (m_Operator == "~") {
48                         bool ret;
49                         try {
50                                 boost::regex expr(m_Operand.GetData());
51                                 String operand = value;
52                                 boost::smatch what;
53                                 ret = boost::regex_search(operand.GetData(), what, expr);
54                         } catch (boost::exception&) {
55                                 Log(LogWarning, "AttributeFilter")
56                                         << "Regex '" << m_Operand << " " << m_Operator << " " << value << "' error.";
57                                 ret = false;
58                         }
59
60                         //Log(LogDebug, "LivestatusListener/AttributeFilter")
61                         //    << "Attribute filter '" << m_Operand + " " << m_Operator << " "
62                         //    << value << "' " << (ret ? "matches" : "doesn't match") << ".";
63
64                         return ret;
65                 } else if (m_Operator == "=~") {
66                         bool ret;
67                         try {
68                                 String operand = value;
69                                 ret = boost::iequals(operand, m_Operand.GetData());
70                         } catch (boost::exception&) {
71                                 Log(LogWarning, "AttributeFilter")
72                                         << "Case-insensitive equality '" << m_Operand << " " << m_Operator << " " << value << "' error.";
73                                 ret = false;
74                         }
75
76                         return ret;
77                 } else if (m_Operator == "~~") {
78                         bool ret;
79                         try {
80                                 boost::regex expr(m_Operand.GetData(), boost::regex::icase);
81                                 String operand = value;
82                                 boost::smatch what;
83                                 ret = boost::regex_search(operand.GetData(), what, expr);
84                         } catch (boost::exception&) {
85                                 Log(LogWarning, "AttributeFilter")
86                                         << "Regex '" << m_Operand << " " << m_Operator << " " << value << "' error.";
87                                 ret = false;
88                         }
89
90                         //Log(LogDebug, "LivestatusListener/AttributeFilter")
91                         //    << "Attribute filter '" << m_Operand << " " << m_Operator << " "
92                         //    << value << "' " << (ret ? "matches" : "doesn't match") << ".";
93
94                         return ret;
95                 } else if (m_Operator == "<") {
96                         if (value.GetType() == ValueNumber)
97                                 return (static_cast<double>(value) < Convert::ToDouble(m_Operand));
98                         else
99                                 return (static_cast<String>(value) < m_Operand);
100                 } else if (m_Operator == ">") {
101                         if (value.GetType() == ValueNumber)
102                                 return (static_cast<double>(value) > Convert::ToDouble(m_Operand));
103                         else
104                                 return (static_cast<String>(value) > m_Operand);
105                 } else if (m_Operator == "<=") {
106                         if (value.GetType() == ValueNumber)
107                                 return (static_cast<double>(value) <= Convert::ToDouble(m_Operand));
108                         else
109                                 return (static_cast<String>(value) <= m_Operand);
110                 } else if (m_Operator == ">=") {
111                         if (value.GetType() == ValueNumber)
112                                 return (static_cast<double>(value) >= Convert::ToDouble(m_Operand));
113                         else
114                                 return (static_cast<String>(value) >= m_Operand);
115                 } else {
116                         BOOST_THROW_EXCEPTION(std::invalid_argument("Unknown operator for column '" + m_Column + "': " + m_Operator));
117                 }
118         }
119
120         return false;
121 }