source: nscp/include/filter_framework.hpp @ 99e4d8f

0.4.00.4.10.4.2stable
Last change on this file since 99e4d8f was 99e4d8f, checked in by Michael Medin <michael@…>, 6 years ago

2007-11-23 MickeM

  • Converted to unicode (damn sometimes I HATE C++) + Added support for escaping " on the /test syntax so now you can do: CheckWMI MaxCrit=3 "MinWarn=1" "Query:load=Select * from win32_Processor"

2007-11-22 MickeM

  • Fixed so the "default path" is correct even when running as a service (issue: #96)
  • Property mode set to 100644
File size: 11.0 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#pragma once
22
23#include <strEx.h>
24#include <checkHelpers.hpp>
25#ifndef NO_BOOST_DEP
26#include <boost/regex.hpp>
27#endif
28
29namespace filters {
30
31        class filter_exception {
32                std::wstring error_;
33        public:
34                filter_exception(std::wstring error) : error_(error) {}
35                std::wstring getMessage() {
36                        return error_;
37                }
38        };
39        struct parse_exception : public filter_exception {
40                parse_exception(std::wstring error) : filter_exception(error) {}
41        };
42        namespace filter {
43                struct sub_string_filter {
44                        static bool filter(std::wstring filter, std::wstring str) {
45                                return str.find(filter) != std::wstring::npos;
46                        }
47                };
48                struct exact_string_filter {
49                        static bool filter(std::wstring filter, std::wstring str) {
50                                return str == filter;
51                        }
52                };
53#ifndef NO_BOOST_DEP
54                struct regexp_string_filter {
55                        static bool filter(boost::wregex filter, std::wstring str) {
56                                return  boost::regex_match(str, filter);
57                        }
58                };
59#endif
60                template <typename TType>
61                struct numeric_max_filter {
62                        static bool filter(TType filter, TType value) {
63                                return value >= filter;
64                        }
65                };
66                template <typename TType>
67                struct numeric_min_filter {
68                        static bool filter(TType filter, TType value) {
69                                return value <= filter;
70                        }
71                };
72                template <typename TType>
73                struct numeric_equals_filter {
74                        static bool filter(TType filter, TType value) {
75                                return value == filter;
76                        }
77                };
78                template <typename TType>
79                struct numeric_nequals_filter {
80                        static bool filter(TType filter, TType value) {
81                                return value != filter;
82                        }
83                };
84                template <typename TType>
85                struct always_true_filter {
86                        static bool filter(TType filter, TType value) {
87                                return true;
88                        }
89                };
90                template <typename TListType, typename TType>
91                struct numeric_inlist_filter {
92                        static bool filter(const TListType &filter, const TType value) {
93                                for (TListType::const_iterator it = filter.begin(); it != filter.end(); ++it) {
94                                        if ((*it) == value)
95                                                return true;
96                                }
97                                return false;
98                        }
99                };
100        }
101        namespace handlers {
102                struct handler_exception : public filter_exception {
103                        handler_exception(std::wstring error) : filter_exception(error) {}
104                };
105                struct string_handler {
106                        static std::wstring parse(std::wstring str) {
107                                return str;
108                        }
109                };
110                template<class TType, class TSubHandler>
111                struct numeric_list_handler {
112                        static std::list<TType> parse(std::wstring str) {
113                                std::list<TType> ret;
114                                std::list<std::wstring> tmp = strEx::splitEx(str, _T(","));
115                                for (std::list<std::wstring>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) {
116                                        ret.push_back(TSubHandler::parse(*it));
117                                }
118                                return ret;
119                        }
120                };
121#ifndef NO_BOOST_DEP
122                struct regexp_handler {
123                        static boost::wregex parse(std::wstring str) {
124                                try {
125                                        return boost::wregex(str);
126                                } catch (const boost::bad_expression e) {
127                                        throw handler_exception(_T("Invalid syntax in regular expression:") + str);
128                                }
129                        }
130                };
131#endif
132                struct eventtype_handler {
133                        static unsigned int parse(std::wstring str) {
134                                if (str == _T("error"))
135                                        return EVENTLOG_ERROR_TYPE;
136                                if (str == _T("warning"))
137                                        return EVENTLOG_WARNING_TYPE;
138                                if (str == _T("info"))
139                                        return EVENTLOG_INFORMATION_TYPE;
140                                if (str == _T("auditSuccess"))
141                                        return EVENTLOG_AUDIT_SUCCESS;
142                                if (str == _T("auditFailure"))
143                                        return EVENTLOG_AUDIT_FAILURE;
144                                return strEx::stoi(str);
145                        }
146                        static std::wstring toString(unsigned int dwType) {
147                                if (dwType == EVENTLOG_ERROR_TYPE)
148                                        return _T("error");
149                                if (dwType == EVENTLOG_WARNING_TYPE)
150                                        return _T("warning");
151                                if (dwType == EVENTLOG_INFORMATION_TYPE)
152                                        return _T("info");
153                                if (dwType == EVENTLOG_AUDIT_SUCCESS)
154                                        return _T("auditSuccess");
155                                if (dwType == EVENTLOG_AUDIT_FAILURE)
156                                        return _T("auditFailure");
157                                return strEx::itos(dwType);
158                        }               
159                };
160                struct eventseverity_handler {
161                        static unsigned int parse(std::wstring str) {
162                                if (str == _T("success"))
163                                        return 0;
164                                if (str == _T("informational"))
165                                        return 1;
166                                if (str == _T("warning"))
167                                        return 2;
168                                if (str == _T("error"))
169                                        return 3;
170                                return strEx::stoi(str);
171                        }
172                        static std::wstring toString(unsigned int dwType) {
173                                if (dwType == 0)
174                                        return _T("success");
175                                if (dwType == 1)
176                                        return _T("informational");
177                                if (dwType == 2)
178                                        return _T("warning");
179                                if (dwType == 3)
180                                        return _T("error");
181                                return strEx::itos(dwType);
182                        }               
183                };      }
184
185        template <typename TFilterType, typename TValueType, class THandler, class TFilter>
186        struct filter_one {
187                TFilterType filter;
188                bool hasFilter_;
189                filter_one() : hasFilter_(false) {}
190                filter_one(const filter_one &other) : hasFilter_(other.hasFilter_), filter(other.filter) {
191                }
192
193                inline bool hasFilter() const {
194                        return hasFilter_;
195                }
196                bool matchFilter(const TValueType value) const {
197                        return TFilter::filter(filter, value);
198                }
199                const filter_one & operator=(std::wstring value) {
200                        hasFilter_ = false;
201                        try {
202                                filter = THandler::parse(value);
203                                hasFilter_ = true;
204                        } catch (handlers::handler_exception e) {
205                                throw parse_exception(e.getMessage());
206                        }
207                        return *this;
208                }
209        };
210
211        typedef filter_one<std::wstring, std::wstring, handlers::string_handler, filter::sub_string_filter> sub_string_filter;
212#ifndef NO_BOOST_DEP
213        typedef filter_one<boost::wregex, std::wstring, handlers::regexp_handler, filter::regexp_string_filter> regexp_string_filter;
214#endif
215        typedef filter_one<std::wstring, std::wstring, handlers::string_handler, filter::exact_string_filter> exact_string_filter;
216
217        struct filter_all_strings {
218                sub_string_filter sub;
219                exact_string_filter exact;
220#ifndef NO_BOOST_DEP
221                regexp_string_filter regexp;
222#endif
223                filter_all_strings() {}
224
225                inline bool hasFilter() const {
226                        return sub.hasFilter()
227#ifndef NO_BOOST_DEP
228                                || regexp.hasFilter()
229#endif
230                                || exact.hasFilter();
231                }
232                bool matchFilter(const std::wstring str) const {
233                        if ((sub.hasFilter())&&(sub.matchFilter(str)))
234                                return true;
235#ifndef NO_BOOST_DEP
236                        else if ((regexp.hasFilter())&&(regexp.matchFilter(str)))
237                                return true;
238#endif
239                        else if ((exact.hasFilter())&&(exact.matchFilter(str)))
240                                return true;
241                        return false;
242                }
243                const filter_all_strings & operator=(std::wstring value) {
244                        strEx::token t = strEx::getToken(value, ':', false);
245                        if (t.first == _T("substr")) {
246                                sub = t.second;
247#ifndef NO_BOOST_DEP
248                        } else if (t.first == _T("regexp")) {
249                                regexp = t.second;
250#endif
251                        } else {
252                                exact = t.first;
253                        }
254                        return *this;
255                }
256        };
257
258        template <typename TType, class THandler>
259        struct filter_all_numeric {
260
261                filter_one<TType, TType, THandler, filter::numeric_max_filter<TType> > max;
262                filter_one<TType, TType, THandler, filter::numeric_min_filter<TType> > min;
263                filter_one<TType, TType, THandler, filter::numeric_equals_filter<TType> > eq;
264                filter_one<TType, TType, THandler, filter::numeric_nequals_filter<TType> > neq;
265                filter_one<std::list<TType>, TType, handlers::numeric_list_handler<TType, THandler>, filter::numeric_inlist_filter<std::list<TType>, TType> > inList;
266
267                filter_all_numeric() {}
268                filter_all_numeric(const filter_all_numeric &other) {
269                        max = other.max;
270                        min = other.min;
271                        eq = other.eq;
272                        neq = other.neq;
273                        inList = other.inList;
274                }
275                inline bool hasFilter() const {
276                        return max.hasFilter() || min.hasFilter() || eq.hasFilter() || neq.hasFilter() || inList.hasFilter();
277                }
278                bool matchFilter(const TType value) const {
279                        if ((max.hasFilter())&&(max.matchFilter(value)))
280                                return true;
281                        else if ((min.hasFilter())&&(min.matchFilter(value)))
282                                return true;
283                        else if ((eq.hasFilter())&&(eq.matchFilter(value)))
284                                return true;
285                        else if ((neq.hasFilter())&&(neq.matchFilter(value)))
286                                return true;
287                        else if ((inList.hasFilter())&&(inList.matchFilter(value)))
288                                return true;
289                        return false;
290                }
291                const filter_all_numeric& operator=(std::wstring value) {
292                        if (value.substr(0,1) == _T(">")) {
293                                max = value.substr(1);
294                        } else if (value.substr(0,1) == _T("<")) {
295                                min = value.substr(1);
296                        } else if (value.substr(0,1) == _T("=")) {
297                                eq = value.substr(1);
298                        } else if (value.substr(0,2) == _T("!=")) {
299                                neq = value.substr(2);
300                        } else if (value.substr(0,3) == _T("in:")) {
301                                inList = value.substr(3);
302                        } else {
303                                throw parse_exception(_T("Unknown filter key: ") + value + _T(" (numeric filters have to have an operator as well ie. foo=>5 or bar==5)"));
304                        }
305                        return *this;
306                }
307        };
308        typedef filter_all_numeric<unsigned long long, checkHolders::time_handler<unsigned long long> > filter_all_times;
309
310        template <typename TFilterType, typename TValueType>
311        struct chained_filter {
312                enum filter_mode {
313                        plus = 1,
314                        minus = 2,
315                        normal = 3,
316                };
317                typedef std::pair<filter_mode,TFilterType> filteritem_type;
318                typedef std::list<filteritem_type> filterlist_type;
319
320                filterlist_type chain;
321                bool filterAll;
322               
323                chained_filter() : filterAll(false) {}
324
325                void push_filter(std::wstring key, TFilterType filter) {
326                        filter_mode mode = normal;
327                        if (key.substr(0,1) == _T("+"))
328                                mode = plus;
329                        if (key.substr(0,1) == _T("-"))
330                                mode = minus;
331                        chain.push_back(filteritem_type(mode, filter));
332                }
333
334                bool hasFilter() {
335                        return !chain.empty();
336                }
337                bool get_inital_state() {
338                        return filterAll;
339                }
340
341                bool match(bool state, const TValueType item) {
342                        bool matched = state;
343                        for (filterlist_type::const_iterator cit = chain.begin(); cit != chain.end(); ++cit ) {
344                                int mode = (*cit).first;
345                                bool bTmpMatched = (*cit).second.matchFilter(item);
346                                if ((mode == minus)&&(bTmpMatched)) {
347                                        // a -<filter> hit so thrash result!
348                                        matched = false;
349                                        break;
350                                } else if ((mode == plus)&&(!bTmpMatched)) {
351                                        // a +<filter> missed hit so thrash result!
352                                        matched = false;
353                                        break;
354                                } else if (bTmpMatched) {
355                                        matched = true;
356                                }
357                        }
358                        return matched;
359                }
360
361        };
362
363
364}
Note: See TracBrowser for help on using the repository browser.