source: nscp/modules/CheckDisk/filter.cpp @ 79f191a

stable
Last change on this file since 79f191a was 79f191a, checked in by Michael Medin <michael@…>, 23 months ago

Release of 0.3.9

  • Property mode set to 100644
File size: 16.1 KB
Line 
1#include "StdAfx.h"
2
3#include <map>
4#include <list>
5
6#include <boost/bind.hpp>
7#include <boost/assign.hpp>
8
9
10#include <parsers/where_parser.hpp>
11#include <parsers/filter/where_filter.hpp>
12#include <parsers/filter/where_filter_impl.hpp>
13
14#include <parsers/where_parser.hpp>
15#include <simple_timer.hpp>
16#include "filter.hpp"
17
18#include <parsers/filter/where_filter_impl.hpp>
19
20#include "file_info.hpp"
21#include "file_finder.hpp"
22
23#include <config.h>
24
25using namespace boost::assign;
26using namespace parsers::where;
27
28file_filter::filter_obj_handler::filter_obj_handler() {
29                insert(types)
30                        (_T("filename"), (type_string))
31                        (_T("name"), (type_string))
32                        (_T("version"), (type_string))
33                        (_T("path"), (type_string))
34                        (_T("line_count"), (type_int))
35                        (_T("size"), (type_size))
36                        (_T("access"), (type_date))
37                        (_T("creation"), (type_date))
38                        (_T("written"), (type_date));
39        }
40
41bool file_filter::filter_obj_handler::has_variable(std::wstring key) {
42        return types.find(key) != types.end();
43}
44parsers::where::value_type file_filter::filter_obj_handler::get_type(std::wstring key) {
45        types_type::const_iterator cit = types.find(key);
46        if (cit == types.end())
47                return parsers::where::type_invalid;
48        return cit->second;
49}
50bool file_filter::filter_obj_handler::can_convert(parsers::where::value_type from, parsers::where::value_type to) {
51        if ((from == parsers::where::type_string)&&(to == type_custom_severity))
52                return true;
53        if ((from == parsers::where::type_string)&&(to == type_custom_type))
54                return true;
55        return false;
56}
57
58file_filter::filter_obj_handler::handler::bound_string_type file_filter::filter_obj_handler::bind_string(std::wstring key) {
59        handler::bound_string_type ret;
60        if (key == _T("filename"))
61                ret = &object_type::get_filename;
62        else if (key == _T("name"))
63                ret = &object_type::get_filename;
64        else if (key == _T("path"))
65                ret = &object_type::get_path;
66        else if (key == _T("version"))
67                ret = &object_type::get_version;
68        else
69                NSC_DEBUG_MSG_STD(_T("Failed to bind (string): ") + key);
70        return ret;
71}
72
73
74file_filter::filter_obj_handler::handler::bound_int_type file_filter::filter_obj_handler::bind_int(std::wstring key) {
75        handler::bound_int_type ret;
76        if (key == _T("size"))
77                ret = &object_type::get_size;
78        else if (key == _T("line_count"))
79                ret = &object_type::get_line_count;
80        else if (key == _T("access"))
81                ret = &object_type::get_access;
82        else if (key == _T("creation"))
83                ret = &object_type::get_creation;
84        else if (key == _T("written"))
85                ret = &object_type::get_write;
86        else
87                NSC_DEBUG_MSG_STD(_T("Failed to bind (int): ") + key);
88        return ret;
89}
90
91bool file_filter::filter_obj_handler::has_function(parsers::where::value_type to, std::wstring name, ast_expr_type subject) {
92        return false;
93}
94file_filter::filter_obj_handler::handler::bound_function_type file_filter::filter_obj_handler::bind_function(parsers::where::value_type to, std::wstring name, ast_expr_type subject) {
95        handler::bound_function_type ret;
96        return ret;
97}
98
99//////////////////////////////////////////////////////////////////////////
100
101
102file_filter::filter_obj file_filter::filter_obj::get(unsigned long long now, const WIN32_FILE_ATTRIBUTE_DATA info, std::wstring path, std::wstring filename) {
103        return file_filter::filter_obj(path, filename, now,
104                (info.ftCreationTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftCreationTime.dwLowDateTime,
105                (info.ftLastAccessTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastAccessTime.dwLowDateTime,
106                (info.ftLastWriteTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastWriteTime.dwLowDateTime,
107                (info.nFileSizeHigh * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.nFileSizeLow
108                );
109};
110file_filter::filter_obj file_filter::filter_obj::get(unsigned long long now, const BY_HANDLE_FILE_INFORMATION info, std::wstring path, std::wstring filename) {
111        return file_filter::filter_obj(path, filename, now,
112                (info.ftCreationTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftCreationTime.dwLowDateTime,
113                (info.ftLastAccessTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastAccessTime.dwLowDateTime,
114                (info.ftLastWriteTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastWriteTime.dwLowDateTime,
115                (info.nFileSizeHigh * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.nFileSizeLow
116        );
117};
118file_filter::filter_obj file_filter::filter_obj::get(unsigned long long now, const WIN32_FIND_DATA info, std::wstring path) {
119        return file_filter::filter_obj(path, info.cFileName, now,
120                (info.ftCreationTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftCreationTime.dwLowDateTime,
121                (info.ftLastAccessTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastAccessTime.dwLowDateTime,
122                (info.ftLastWriteTime.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.ftLastWriteTime.dwLowDateTime,
123                (info.nFileSizeHigh * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)info.nFileSizeLow
124                );
125        //attributes = info.dwFileAttributes;
126};
127file_filter::filter_obj file_filter::filter_obj::get(unsigned long long now, std::wstring path, std::wstring filename) {
128        WIN32_FILE_ATTRIBUTE_DATA data;
129        if (!GetFileAttributesEx((path + _T("\\") + filename).c_str(), GetFileExInfoStandard, reinterpret_cast<LPVOID>(&data))) {
130                filter_obj ret;
131                ret.error(_T("Could not open file (2) ") + path + _T("\\") + filename + _T(": ") + error::lookup::last_error());
132                return ret;
133        }
134        return get(now, data, path, filename);
135}
136file_filter::filter_obj file_filter::filter_obj::get(std::wstring file) {
137        FILETIME now;
138        GetSystemTimeAsFileTime(&now);
139        unsigned __int64 nowi64 = ((now.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)now.dwLowDateTime);
140        return get(nowi64, file);
141}
142file_filter::filter_obj file_filter::filter_obj::get(unsigned long long now, std::wstring file) {
143
144        BY_HANDLE_FILE_INFORMATION _info;
145
146        HANDLE hFile = CreateFile(file.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
147                0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
148        if (hFile == INVALID_HANDLE_VALUE) {
149                filter_obj ret;
150                ret.error(_T("Could not open file (2) ") + file + _T(": ") + error::lookup::last_error());
151                return ret;
152        }
153        GetFileInformationByHandle(hFile, &_info);
154        CloseHandle(hFile);
155        return get(now, _info, file_helpers::meta::get_path(file), file_helpers::meta::get_filename(file));
156}
157
158
159
160std::wstring file_filter::filter_obj::get_version() {
161        if (cached_version)
162                return *cached_version;
163        std::wstring fullpath = path+_T("\\")+filename;
164
165        DWORD dwDummy;
166        DWORD dwFVISize = GetFileVersionInfoSize(fullpath.c_str(),&dwDummy);
167        if (dwFVISize == 0)
168                return _T("");
169        LPBYTE lpVersionInfo = new BYTE[dwFVISize+1];
170        if (!GetFileVersionInfo(fullpath.c_str(),0,dwFVISize,lpVersionInfo)) {
171                delete [] lpVersionInfo;
172                error(_T("Failed to get version for ") + fullpath + _T(": ") + error::lookup::last_error());
173                return _T("");
174        }
175        UINT uLen;
176        VS_FIXEDFILEINFO *lpFfi;
177        if (!VerQueryValue( lpVersionInfo , _T("\\") , (LPVOID *)&lpFfi , &uLen )) {
178                delete [] lpVersionInfo;
179                error(_T("Failed to query version for ") + fullpath + _T(": ") + error::lookup::last_error());
180                return _T("");
181        }
182        DWORD dwFileVersionMS = lpFfi->dwFileVersionMS;
183        DWORD dwFileVersionLS = lpFfi->dwFileVersionLS;
184        delete [] lpVersionInfo;
185        DWORD dwLeftMost = HIWORD(dwFileVersionMS);
186        DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
187        DWORD dwSecondRight = HIWORD(dwFileVersionLS);
188        DWORD dwRightMost = LOWORD(dwFileVersionLS);
189        cached_version.reset(strEx::itos(dwLeftMost) + _T(".") +
190                strEx::itos(dwSecondLeft) + _T(".") +
191                strEx::itos(dwSecondRight) + _T(".") +
192                strEx::itos(dwRightMost));
193        return *cached_version;
194}
195
196unsigned long file_filter::filter_obj::get_line_count() {
197        if (cached_count)
198                return *cached_count;
199
200        unsigned long count = 0;
201        std::wstring fullpath = path+_T("\\")+filename;
202        FILE * pFile = fopen(strEx::wstring_to_string(fullpath).c_str(),"r");;
203        if (pFile==NULL)
204                return 0;
205        char c;
206        do {
207                c = fgetc (pFile);
208                if (c == '\r') {
209                        c = fgetc (pFile);
210                        count++;
211                } else if (c == '\n') {
212                        c = fgetc (pFile);
213                        count++;
214                }
215        } while (c != EOF);
216        fclose (pFile);
217        cached_count.reset(count);
218        return *cached_count;
219}
220
221
222std::wstring file_filter::filter_obj::render(std::wstring syntax, std::wstring datesyntax) {
223        strEx::replace(syntax, _T("%path%"), path);
224        strEx::replace(syntax, _T("%filename%"), filename);
225        strEx::replace(syntax, _T("%creation%"), strEx::format_filetime(ullCreationTime, datesyntax));
226        strEx::replace(syntax, _T("%access%"), strEx::format_filetime(ullLastAccessTime, datesyntax));
227        strEx::replace(syntax, _T("%write%"), strEx::format_filetime(ullLastWriteTime, datesyntax));
228        strEx::replace(syntax, _T("%creation-raw%"), strEx::itos(ullCreationTime));
229        strEx::replace(syntax, _T("%access-raw%"), strEx::itos(ullLastAccessTime));
230        strEx::replace(syntax, _T("%write-raw%"), strEx::itos(ullLastWriteTime));
231        strEx::replace(syntax, _T("%now-raw%"), strEx::itos(ullNow));
232/*
233        strEx::replace(syntax, _T("%creation-d%"), strEx::format_filetime(ullCreationTime, DATE_FORMAT));
234        strEx::replace(syntax, _T("%access-d%"), strEx::format_filetime(ullLastAccessTime, DATE_FORMAT));
235        strEx::replace(syntax, _T("%write-d%"), strEx::format_filetime(ullLastWriteTime, DATE_FORMAT));
236*/
237        strEx::replace(syntax, _T("%size%"), strEx::itos_as_BKMG(ullSize));
238        if (cached_version)
239                strEx::replace(syntax, _T("%version%"), *cached_version);
240        if (cached_count)
241                strEx::replace(syntax, _T("%line_count%"), strEx::itos(*cached_count));
242        return syntax;
243}
244
245//////////////////////////////////////////////////////////////////////////
246
247struct where_mode_filter : public file_filter::filter_engine_type {
248        file_filter::filter_argument data;
249        parsers::where::parser<file_filter::filter_obj_handler> ast_parser;
250        file_filter::filter_obj_handler object_handler;
251
252        where_mode_filter(file_filter::filter_argument data) : data(data) {}
253        bool boot() { return true; }
254
255        bool validate(std::wstring &message) {
256                if (data->debug)
257                        data->error->report_debug(_T("Parsing: ") + data->filter);
258
259                if (!ast_parser.parse(data->filter)) {
260                        data->error->report_error(_T("Parsing failed of '") + data->filter + _T("' at: ") + ast_parser.rest);
261                message = _T("Parsing failed: ") + ast_parser.rest;
262                return false;
263                }
264                if (data->debug)
265                        data->error->report_debug(_T("Parsing succeeded: ") + ast_parser.result_as_tree());
266
267                if (!ast_parser.derive_types(object_handler) || object_handler.has_error()) {
268                        message = _T("Invalid types: ") + object_handler.get_error();
269                        return false;
270                }
271                        if (data->debug)
272                                data->error->report_debug(_T("Type resolution succeeded: ") + ast_parser.result_as_tree());
273
274                if (!ast_parser.bind(object_handler) || object_handler.has_error()) {
275                        message = _T("Variable and function binding failed: ") + object_handler.get_error();
276                        return false;
277                }
278                        if (data->debug)
279                                data->error->report_debug(_T("Binding succeeded: ") + ast_parser.result_as_tree());
280
281                if (!ast_parser.static_eval(object_handler) || object_handler.has_error()) {
282                        message = _T("Static evaluation failed: ") + object_handler.get_error();
283                        return false;
284                }
285                        if (data->debug)
286                                data->error->report_debug(_T("Static evaluation succeeded: ") + ast_parser.result_as_tree());
287
288                return true;
289        }
290
291        bool match(file_filter::flyweight_type &record) {
292                bool ret = ast_parser.evaluate(record);
293                if (record.has_error()) {
294                                data->error->report_error(_T("Error: ") + record.get_error());
295                }
296                return ret;
297        }
298
299        std::wstring get_name() {
300                return _T("where");
301        }
302        std::wstring get_subject() { return data->filter; }
303};
304
305//////////////////////////////////////////////////////////////////////////
306
307file_filter::file_finder_data_arguments::file_finder_data_arguments(std::wstring pattern, int max_depth, file_filter::filter_argument_type::error_type error, std::wstring syntax, std::wstring datesyntax, bool debug)
308                : debugThreshold(0), bFilterIn(true), bFilterAll(false), bShowDescriptions(false), max_level(max_depth), pattern(pattern)
309                , file_filter::file_finder_data_arguments::parent_type(error, syntax, datesyntax, debug)
310{
311        FILETIME ft_now;
312        GetSystemTimeAsFileTime(&ft_now);
313        now = ((ft_now.dwHighDateTime * ((unsigned long long)MAXDWORD+1)) + (unsigned long long)ft_now.dwLowDateTime);
314}
315
316//////////////////////////////////////////////////////////////////////////
317
318
319
320struct old_file_engine : public file_filter::filter_engine_type {
321
322        static const int filter_plus = 1;
323        static const int filter_minus = 2;
324        static const int filter_normal = 3;
325
326        file_filter::filter_argument arguments;
327        old_file_engine(file_filter::filter_argument arguments) : arguments(arguments) {}
328
329
330        bool boot() { return true; }
331        bool validate(std::wstring &message) {
332                if (arguments->old_chain.empty()) {
333                        message = _T("No filters specified try adding: filter+generated=>2d");
334                        return false;
335                }
336                return true;
337        }
338        bool match(file_filter::filter_obj &record) {
339
340                bool bMatch = !arguments->bFilterIn;
341                for (file_filter::filter_argument_type::filterlist_type::const_iterator cit3 = arguments->old_chain.begin(); cit3 != arguments->old_chain.end(); ++cit3 ) {
342                        bool bTmpMatched = (*cit3).second.matchFilter(&record);
343                        int mode = (*cit3).first;
344
345                        if ((mode == filter_minus)&&(bTmpMatched)) {
346                                // a -<filter> hit so thrash item and bail out!
347                                if (arguments->debug)
348                                        arguments->error->report_debug(_T("Matched: - ") + (*cit3).second.getValue() + _T(" for: ") + record.render(arguments->syntax, DATE_FORMAT));
349                                bMatch = false;
350                                break;
351                        } else if ((mode == filter_plus)&&(!bTmpMatched)) {
352                                // a +<filter> missed hit so thrash item and bail out!
353                                if (arguments->debug)
354                                        arguments->error->report_debug(_T("Matched (missed): + ") + (*cit3).second.getValue() + _T(" for: ") + record.render(arguments->syntax, DATE_FORMAT));
355                                bMatch = false;
356                                break;
357                        } else if (bTmpMatched) {
358                                if (arguments->debug)
359                                        arguments->error->report_debug(_T("Matched: . (contiunue): ") + (*cit3).second.getValue() + _T(" for: ") + record.render(arguments->syntax, DATE_FORMAT));
360                                bMatch = true;
361                        }
362                }
363                return bMatch;
364        }
365        std::wstring get_name() { return _T("old"); }
366        std::wstring get_subject() { return _T("TODO"); }
367
368};
369
370
371struct size_file_engine : public file_filter::filesize_engine_interface_type {
372        size_file_engine() : size(0) {}
373
374        bool boot() { return true; }
375        bool validate(std::wstring &message) {
376                return true;
377        }
378        bool match(file_filter::filter_obj &record) {
379                if (!file_helpers::checks::is_directory(record.attributes)) {
380                        size += record.get_size();
381                }
382                return true;
383        }
384        std::wstring get_name() { return _T("file-size"); }
385        std::wstring get_subject() { return _T("TODO"); }
386        unsigned long long get_size() {
387                return size;
388        }
389private: 
390        unsigned long long size;
391
392};
393
394
395
396//////////////////////////////////////////////////////////////////////////
397file_filter::filter_engine file_filter::factories::create_engine(file_filter::filter_argument arg) {
398        return filter_engine(new where_mode_filter(arg));
399}
400file_filter::filter_engine file_filter::factories::create_old_engine(file_filter::filter_argument arg) {
401        return filter_engine(new old_file_engine(arg));
402}
403file_filter::filesize_engine_interface file_filter::factories::create_size_engine() {
404        return filesize_engine_interface(new size_file_engine());
405}
406file_filter::filter_argument file_filter::factories::create_argument(std::wstring pattern, int max_depth, std::wstring syntax, std::wstring datesyntax) {
407        return filter_argument(new file_filter::file_finder_data_arguments(pattern, max_depth, file_filter::filter_argument_type::error_type(new where_filter::nsc_error_handler()), syntax, datesyntax));
408}
409
410file_filter::filter_result file_filter::factories::create_result(file_filter::filter_argument arg) {
411        return filter_result(new where_filter::simple_count_result<flyweight_type>(arg));
412}
413
414
415
416
417
Note: See TracBrowser for help on using the repository browser.