From 141f2691dbf94f67337fb2339075ac6c84027d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Wed, 9 Dec 2020 21:10:33 +0100 Subject: [PATCH] Replace track_users by filter_users plugin --- plugins/display/filter_users.py | 197 ++++++++++++++++++++++++++++++++ plugins/display/track_users.py | 64 +---------- 2 files changed, 199 insertions(+), 62 deletions(-) create mode 100644 plugins/display/filter_users.py diff --git a/plugins/display/filter_users.py b/plugins/display/filter_users.py new file mode 100644 index 0000000..92bdbcd --- /dev/null +++ b/plugins/display/filter_users.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +# +# Copyright Grégory Soutadé 2020 + +# This file is part of iwla + +# iwla is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# iwla is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with iwla. If not, see . +# + +import re + +from iwla import IWLA +from iplugin import IPlugin +from display import * + +""" +Display hook + +Filter users + +Plugin requirements : + None + +Conf values needed : + filtered_users : list of filters + filtered_ip : list of ip (string) + create_filtered_page* + +Filter is a list of filter description combined by AND operator +Filter description is a list of 3 elements : + + * Field to match in visits + * Operator '=', '==', '!=', '>', '>=', '<', '<=' for int value + * Operator '=', '==', '!=', 'in', 'match' for str value + * Target value + +For easiest config, you can indicate both 'remote_addr' or 'ip' in field element + +Output files : + OUTPUT_ROOT/year/month/index.html + OUTPUT_ROOT/year/month/filtered_users.html + +Statistics creation : + None + +Statistics update : + None + +Statistics deletion : + None +""" + +class IWLADisplayFilterUsers(IPlugin): + def __init__(self, iwla): + super(IWLADisplayFilterUsers, self).__init__(iwla) + self.API_VERSION = 1 + + def _check_filter(self, _filter): + if len(_filter) != 3: + raise Exception('Bad filter ' + ' '.join(_filter)) + (field, operator, value) = _filter + try: + if type(value) == str: + value = int(value, 10) + _filter[2] = value + if operator not in ('=', '==', '!=', '>', '>=', '<', '<='): + raise Exception('Bad filter ' + ' '.join(_filter)) + except Exception as e: + if field == 'ip': + _filter[0] = 'remote_addr' + if operator not in ('=', '==', '!=', 'in', 'match'): + raise Exception('Bad filter ' + ' '.join(_filter)) + if operator == 'match': + _filter[2] = re.compile(value) + + def load(self): + self.create_filtered_page = self.iwla.getConfValue('create_filtered_page', True) + self.filters = self.iwla.getConfValue('filtered_users', []) + self.ip_filters = self.iwla.getConfValue('filtered_ip', []) + for _filter in self.filters: + for sub_filter in _filter: + self._check_filter(sub_filter) + return True + + def __do_filter(self, hit, _filter): + (field, operator, value) = _filter + if not field in hit.keys(): return False + hit_value = hit[field] + # In dict, we have something like : {dayX : value} were day0 is total + if type(value) == int and type(hit_value) == dict: + hit_value = list(hit_value.values())[0] + if operator == '=' or operator == '==': + return hit_value == value + elif operator == 'in': + return hit_value in value + elif operator == 'match': + return re.match(value, hit_value) + elif operator == '!=': + return hit_value != value + elif operator == '<': + return hit_value < value + elif operator == '<=': + return hit_value <= value + elif operator == '>': + return hit_value > value + elif operator == '>=': + return hit_value >= value + + def _do_filter(self, ip, hits): + if ip in self.ip_filters: + return True + + for _filter in self.filters: + filtered = True + for sub_filter in _filter: + if not self.__do_filter(hits[ip], sub_filter): + filtered = False + break + if filtered: + return True + return False + + def hook(self): + display = self.iwla.getDisplay() + hits = self.iwla.getValidVisitors() + stats = {} + self.filtered_users = [] + + if len(self.filters) or len(self.ip_filters): + for (key,value) in hits.items(): + if self._do_filter(key, hits): + self.filtered_users.append(hits[key]) + + # All in a page + if self.create_filtered_page: + title = createCurTitle(self.iwla, u'Filtered users') + filename = 'filtered_users.html' + path = self.iwla.getCurDisplayPath(filename) + + page = display.createPage(title, path, self.iwla.getConfValue('css_path', [])) + table = display.createBlock(DisplayHTMLBlockTable, self.iwla._(u'Filtered users'), [self.iwla._(u'Pages'), self.iwla._(u'Last Access')]) + table.setColsCSSClass(['iwla_page', '']) + for filtered_user in self.filtered_users: + ip = filtered_user['remote_addr'] + if 'dns_name_replaced' in hits[ip].keys(): + ip_title = '%s [%s]' % (hits[ip]['remote_addr'], ip) + else: + ip_title = '%s' % (ip) + table.appendRow([ip_title, '']) + nb_hits = 0 + nb_pages = 0 + for r in hits[ip]['requests'][::-1]: + uri = r['extract_request']['extract_uri'].lower() + if not self.iwla.hasBeenViewed(r): continue + if not self.iwla.isPage(uri) or\ + self.iwla.isMultimediaFile(uri): + nb_hits += 1 + continue + + nb_pages += 1 + uri = "%s%s" % (r.get('server_name', ''), + r['extract_request']['extract_uri']) + table.appendRow([generateHTMLLink(uri), time.asctime(r['time_decoded'])]) + stats[ip] = (nb_pages, nb_hits) + page.appendBlock(table) + + display.addPage(page) + + # Last access in index + title = self.iwla._(u'Filtered users') + if self.create_filtered_page: + link = '%s' % (filename, self.iwla._(u'Details')) + title = '%s - %s' % (title, link) + + index = self.iwla.getDisplayIndex() + + table = display.createBlock(DisplayHTMLBlockTable, title, [self.iwla._(u'Host'), self.iwla._(u'Last Access'), self.iwla._(u'Pages'), self.iwla._(u'Hits')]) + table.setColsCSSClass(['', '', 'iwla_page', 'iwla_hit']) + for filtered_user in self.filtered_users: + ip = filtered_user['remote_addr'] + if 'dns_name_replaced' in hits[ip].keys(): + ip_title = '%s [%s]' % (hits[ip]['remote_addr'], ip) + else: + ip_title = ip + table.appendRow([ip_title, time.asctime(hits[ip]['last_access']), stats[ip][0], stats[ip][1]]) + index.appendBlock(table) diff --git a/plugins/display/track_users.py b/plugins/display/track_users.py index c653e4a..ef1c481 100644 --- a/plugins/display/track_users.py +++ b/plugins/display/track_users.py @@ -54,69 +54,9 @@ class IWLADisplayTrackUsers(IPlugin): def __init__(self, iwla): super(IWLADisplayTrackUsers, self).__init__(iwla) self.API_VERSION = 1 - self.conf_requires = ['tracked_ip'] def load(self): - self.create_tracked_page = self.iwla.getConfValue('create_tracked_page', True) - self.tracked_ip = self.iwla.getConfValue('tracked_ip', []) - - return True + raise Exception('Track users is deprecated, use filter_users instead') def hook(self): - display = self.iwla.getDisplay() - hits = self.iwla.getCurrentVisits() - stats = {} - - # All in a page - if self.create_tracked_page: - title = createCurTitle(self.iwla, u'Tracked users') - filename = 'tracked_users.html' - path = self.iwla.getCurDisplayPath(filename) - - page = display.createPage(title, path, self.iwla.getConfValue('css_path', [])) - table = display.createBlock(DisplayHTMLBlockTable, self.iwla._(u'Tracked users'), [self.iwla._(u'Pages'), self.iwla._(u'Last Access')]) - table.setColsCSSClass(['iwla_page', '']) - for ip in self.tracked_ip: - if not ip in hits.keys(): continue - if 'dns_name_replaced' in hits[ip].keys(): - ip_title = '%s [%s]' % (hits[ip]['remote_addr'], ip) - else: - ip_title = '%s' % (ip) - table.appendRow([ip_title, '']) - nb_hits = 0 - nb_pages = 0 - for r in hits[ip]['requests'][::-1]: - uri = r['extract_request']['extract_uri'].lower() - if not self.iwla.hasBeenViewed(r): continue - if not self.iwla.isPage(uri) or\ - self.iwla.isMultimediaFile(uri): - nb_hits += 1 - continue - - nb_pages += 1 - uri = "%s%s" % (r.get('server_name', ''), - r['extract_request']['extract_uri']) - table.appendRow([generateHTMLLink(uri), time.asctime(r['time_decoded'])]) - stats[ip] = (nb_pages, nb_hits) - page.appendBlock(table) - - display.addPage(page) - - # Last access in index - title = self.iwla._(u'Tracked users') - if self.create_tracked_page: - link = '%s' % (filename, self.iwla._(u'Details')) - title = '%s - %s' % (title, link) - - index = self.iwla.getDisplayIndex() - - table = display.createBlock(DisplayHTMLBlockTable, title, [self.iwla._(u'Host'), self.iwla._(u'Last Access'), self.iwla._(u'Pages'), self.iwla._(u'Hits')]) - table.setColsCSSClass(['', '', 'iwla_page', 'iwla_hit']) - for ip in self.tracked_ip: - if not ip in hits.keys(): continue - if 'dns_name_replaced' in hits[ip].keys(): - ip_title = '%s [%s]' % (hits[ip]['remote_addr'], ip) - else: - ip_title = ip - table.appendRow([ip_title, time.asctime(hits[ip]['last_access']), stats[ip][0], stats[ip][1]]) - index.appendBlock(table) + pass