]> granicus.if.org Git - icinga2/blob - lib/livestatus/attributefilter.cpp
Merge branch 'support/2.5'
[icinga2] / lib / livestatus / attributefilter.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2016 Icinga Development Team (https://www.icinga.org/)  *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "livestatus/attributefilter.hpp"
21 #include "base/convert.hpp"
22 #include "base/array.hpp"
23 #include "base/objectlock.hpp"
24 #include "base/logger.hpp"
25 #include <boost/regex.hpp>
26 #include <boost/algorithm/string/predicate.hpp>
27
28 using namespace icinga;
29
30 AttributeFilter::AttributeFilter(const String& column, const String& op, const String& operand)
31         : m_Column(column), m_Operator(op), m_Operand(operand)
32 { }
33
34 bool AttributeFilter::Apply(const Table::Ptr& table, const Value& row)
35 {
36         Column column = table->GetColumn(m_Column);
37
38         Value value = column.ExtractValue(row);
39
40         if (value.IsObjectType<Array>()) {
41                 Array::Ptr array = value;
42
43                 if (m_Operator == ">=" || m_Operator == "<") {
44                         bool negate = (m_Operator == "<");
45
46                         ObjectLock olock(array);
47                         for (const String& item : array) {
48                                 if (item == m_Operand)
49                                         return !negate; /* Item found in list. */
50                         }
51
52                         return negate; /* Item not found in list. */
53                 } else if (m_Operator == "=") {
54                         return (array->GetLength() == 0);
55                 } else {
56                         BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid operator for column '" + m_Column + "': " + m_Operator + " (expected '>=' or '=')."));
57                 }
58         } else {
59                 if (m_Operator == "=") {
60                         if (value.GetType() == ValueNumber || value.GetType() == ValueBoolean)
61                                 return (static_cast<double>(value) == Convert::ToDouble(m_Operand));
62                         else
63                                 return (static_cast<String>(value) == m_Operand);
64                 } else if (m_Operator == "~") {
65                         bool ret;
66                         try {
67                                 boost::regex expr(m_Operand.GetData());
68                                 String operand = value;
69                                 boost::smatch what;
70                                 ret = boost::regex_search(operand.GetData(), what, expr);
71                         } catch (boost::exception&) {
72                                 Log(LogWarning, "AttributeFilter")
73                                     << "Regex '" << m_Operand << " " << m_Operator << " " << value << "' error.";
74                                 ret = false;
75                         }
76
77                         //Log(LogDebug, "LivestatusListener/AttributeFilter")
78                         //    << "Attribute filter '" << m_Operand + " " << m_Operator << " "
79                         //    << value << "' " << (ret ? "matches" : "doesn't match") << ".";
80
81                         return ret;
82                 } else if (m_Operator == "=~") {
83                         bool ret;
84                         try {
85                                 String operand = value;
86                                 ret = boost::iequals(operand, m_Operand.GetData());
87                         } catch (boost::exception&) {
88                                 Log(LogWarning, "AttributeFilter")
89                                     << "Case-insensitive equality '" << m_Operand << " " << m_Operator << " " << value << "' error.";
90                                 ret = false;
91                         }
92
93                         return ret;
94                 } else if (m_Operator == "~~") {
95                         bool ret;
96                         try {
97                                 boost::regex expr(m_Operand.GetData(), boost::regex::icase);
98                                 String operand = value;
99                                 boost::smatch what;
100                                 ret = boost::regex_search(operand.GetData(), what, expr);
101                         } catch (boost::exception&) {
102                                 Log(LogWarning, "AttributeFilter")
103                                     << "Regex '" << m_Operand << " " << m_Operator << " " << value << "' error.";
104                                 ret = false;
105                         }
106
107                         //Log(LogDebug, "LivestatusListener/AttributeFilter")
108                         //    << "Attribute filter '" << m_Operand << " " << m_Operator << " "
109                         //    << value << "' " << (ret ? "matches" : "doesn't match") << ".";
110
111                         return ret;
112                 } else if (m_Operator == "<") {
113                         if (value.GetType() == ValueNumber)
114                                 return (static_cast<double>(value) < Convert::ToDouble(m_Operand));
115                         else
116                                 return (static_cast<String>(value) < m_Operand);
117                 } else if (m_Operator == ">") {
118                         if (value.GetType() == ValueNumber)
119                                 return (static_cast<double>(value) > Convert::ToDouble(m_Operand));
120                         else
121                                 return (static_cast<String>(value) > m_Operand);
122                 } else if (m_Operator == "<=") {
123                         if (value.GetType() == ValueNumber)
124                                 return (static_cast<double>(value) <= Convert::ToDouble(m_Operand));
125                         else
126                                 return (static_cast<String>(value) <= m_Operand);
127                 } else if (m_Operator == ">=") {
128                         if (value.GetType() == ValueNumber)
129                                 return (static_cast<double>(value) >= Convert::ToDouble(m_Operand));
130                         else
131                                 return (static_cast<String>(value) >= m_Operand);
132                 } else {
133                         BOOST_THROW_EXCEPTION(std::invalid_argument("Unknown operator for column '" + m_Column + "': " + m_Operator));
134                 }
135         }
136
137         return false;
138 }