summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc/filter.inc.php
diff options
context:
space:
mode:
authorChristian Klinger2016-07-13 12:40:58 +0200
committerChristian Klinger2016-07-13 12:40:58 +0200
commitc5712e1c26b31afd38ebd8b7d79b0740c0dd0d60 (patch)
treec6bca52b94d12014999d97026dc5f291a27b8b29 /modules-available/statistics/inc/filter.inc.php
parentfixed bug. (diff)
downloadslx-admin-c5712e1c26b31afd38ebd8b7d79b0740c0dd0d60.tar.gz
slx-admin-c5712e1c26b31afd38ebd8b7d79b0740c0dd0d60.tar.xz
slx-admin-c5712e1c26b31afd38ebd8b7d79b0740c0dd0d60.zip
Squashed commit of the following:
commit af19d2aa593a4b4b068a5bc3707d74378625d774 Author: Christian Klinger <spam@klinch.de> Date: Wed Jul 13 12:32:17 2016 +0200 added sorting functionality. commit 0030ebebb49bad18fba8e74184d331be5485ed4e Author: Christian Klinger <spam@klinch.de> Date: Fri Jul 8 16:09:16 2016 +0200 small improvements. commit 8dc5ee1173ffbc6e689f3197ad4d1ecf700a9374 Author: Christian Klinger <spam@klinch.de> Date: Fri Jul 8 12:49:29 2016 +0200 added location fiter. commit 63a2da244a6def5cdd76c654bd5a6a0c108cc47b Author: Christian Klinger <spam@klinch.de> Date: Fri Jul 8 12:25:15 2016 +0200 most filters should work. commit 847536b34cec0194c58cb41a17006a8bd88f748d Author: Christian Klinger <spam@klinch.de> Date: Tue Jul 5 15:57:38 2016 +0200 rudimentary filter options.
Diffstat (limited to 'modules-available/statistics/inc/filter.inc.php')
-rw-r--r--modules-available/statistics/inc/filter.inc.php205
1 files changed, 205 insertions, 0 deletions
diff --git a/modules-available/statistics/inc/filter.inc.php b/modules-available/statistics/inc/filter.inc.php
new file mode 100644
index 00000000..0f1a0d20
--- /dev/null
+++ b/modules-available/statistics/inc/filter.inc.php
@@ -0,0 +1,205 @@
+<?php
+
+/* base class with rudimentary SQL generation abilities.
+ * WARNING: argument is escaped, but $column and $operator are passed unfiltered into SQL */
+class Filter
+{
+ public $column;
+ public $operator;
+ public $argument;
+ public function __construct($column, $operator, $argument = null)
+ {
+ $this->column = trim($column);
+ $this->operator = trim($operator);
+ $this->argument = trim($argument);
+ }
+ /* returns a where clause and adds needed operators to the passed array */
+ public function whereClause(&$args, &$joins)
+ {
+ global $unique_key;
+ $key = $this->column.'_arg' . ($unique_key++);
+
+ /* check if we have to do some parsing*/
+ if (Page_Statistics::$columns[$this->column]['type'] == 'date') {
+ $args[$key] = strtotime($this->argument);
+ } else {
+ $args[$key] = $this->argument;
+ }
+
+ $op = $this->operator;
+ if ($this->operator == '~') {
+ $op = 'LIKE';
+ } elseif ($this->operator == '!~') {
+ $op = 'NOT LIKE';
+ }
+
+ return $this->column.' '.$op.' :'.$key;
+ }
+ /* parse a query into an array of filters */
+ public static function parseQuery($query)
+ {
+ $operators = ['<=', '>=', '!=', '!~', '=', '~', '<', '>'];
+ $filters = [];
+ foreach (explode(',', $query) as $q) {
+ $q = trim($q);
+ /* find position of first operator */
+ $pos = 10000;
+ $operator;
+ foreach ($operators as $op) {
+ $newpos = strpos($q, $op);
+ if ($newpos > -1 && ($newpos < $pos)) {
+ $pos = $newpos;
+ $operator = $op;
+ }
+ }
+ if ($pos == 10000) {
+ error_log("couldn't find operator in segment ".$q);
+ /* TODO */
+ continue;
+ }
+ $lhs = trim(substr($q, 0, $pos));
+ $rhs = trim(substr($q, $pos + strlen($operator)));
+
+ if ($lhs == 'gbram') {
+ $filters[] = new RamGbFilter($operator, $rhs);
+ } elseif ($lhs == 'state') {
+ error_log('new state filter with ' . $rhs);
+ $filters[] = new StateFilter($operator, $rhs);
+ } elseif ($lhs == 'hddgb') {
+ $filters[] = new Id44Filter($operator, $rhs);
+ } elseif ($lhs == 'location') {
+ $filters[] = new LocationFilter($operator, $rhs);
+ } elseif ($lhs == 'subnet') {
+ $filters[] = new SubnetFilter($operator, $rhs);
+ } else {
+ if (array_key_exists($lhs, Page_Statistics::$columns) && Page_Statistics::$columns[$lhs]['column']) {
+ $filters[] = new Filter($lhs, $operator, $rhs);
+ } else {
+ Message::addError('invalid-filter');
+ }
+ }
+ }
+
+ return $filters;
+ }
+}
+
+class RamGbFilter extends Filter
+{
+ public function __construct($operator, $argument)
+ {
+ parent::__construct('mbram', $operator, $argument);
+ }
+ public function whereClause(&$args, &$joins)
+ {
+ global $SIZE_RAM;
+ $lower = floor(Page_Statistics::findBestValue($SIZE_RAM, (int) $this->argument, false) * 1024 - 100);
+ $upper = ceil(Page_Statistics::findBestValue($SIZE_RAM, (int) $this->argument, true) * 1024 + 100);
+ if ($this->operator == '=') {
+ return " mbram BETWEEN $lower AND $upper";
+ } elseif ($this->operator == '<') {
+ return " mbram < $lower";
+ } elseif ($this->operator == '<=') {
+ return " mbram <= $upper";
+ } elseif ($this->operator == '>') {
+ return " mbram > $upper";
+ } elseif ($this->operator == '>=') {
+ return " mbram >= $lower";
+ } elseif ($this->operator == '!=') {
+ return " (mbram < $lower OR mbram > $upper)";
+ } else {
+ error_log("unimplemented operator in RamGbFilter: $this->operator");
+
+ return ' 1';
+ }
+ }
+}
+class Id44Filter extends Filter
+{
+ public function __construct($operator, $argument)
+ {
+ parent::__construct('id44mb', $operator, $argument);
+ }
+ public function whereClause(&$args, &$joins)
+ {
+ global $SIZE_ID44;
+ $lower = floor(Page_Statistics::findBestValue($SIZE_ID44, $this->argument, false) * 1024 - 100);
+ $upper = ceil(Page_Statistics::findBestValue($SIZE_ID44, $this->argument, true) * 1024 + 100);
+
+ if ($this->operator == '=') {
+ return " id44mb BETWEEN $lower AND $upper";
+ } elseif ($this->operator == '!=') {
+ return " id44mb < $lower OR id44mb > $upper";
+ } elseif ($this->operator == '<=') {
+ return " id44mb < $upper";
+ } elseif ($this->operator == '>=') {
+ return " id44mb > $lower";
+ } elseif ($this->operator == '<') {
+ return " id44mb < $lower";
+ } elseif ($this->operator == '>') {
+ return " id44mb > $upper";
+ } else {
+ error_log("unimplemented operator in Id44Filter: $this->operator");
+
+ return ' 1';
+ }
+ }
+}
+class StateFilter extends Filter
+{
+ public function __construct($operator, $argument)
+ {
+ $this->operator = $operator;
+ $this->argument = $argument;
+ }
+
+ public function whereClause(&$args, &$joins)
+ {
+ $neg = $this->operator == '!=' ? 'NOT ' : '';
+ if ($this->argument === 'on') {
+ return " $neg (lastseen + 600 > UNIX_TIMESTAMP() ) ";
+ } elseif ($this->argument === 'off') {
+ return " $neg (lastseen + 600 < UNIX_TIMESTAMP() ) ";
+ } elseif ($this->argument === 'idle') {
+ return " $neg (lastseen + 600 > UNIX_TIMESTAMP() AND logintime = 0 ) ";
+ } elseif ($this->argument === 'occupied') {
+ return " $neg (lastseen + 600 > UNIX_TIMESTAMP() AND logintime <> 0 ) ";
+ } else {
+ Message::addError('invalid-filter');
+
+ return ' 1';
+ }
+ }
+}
+
+class LocationFilter extends Filter
+{
+ public function __construct($operator, $argument) {
+ parent::__construct('locationid', $operator, $argument);
+ }
+
+ public function whereClause(&$args, &$joins) {
+ settype($this->argument, 'int');
+ if ($this->argument === 0) {
+ $joins[] = 'LEFT JOIN subnet s ON (INET_ATON(machine.clientip) BETWEEN s.startaddr AND s.endaddr)';
+ return 'machine.locationid IS NULL AND s.locationid IS NULL';
+ } else {
+ $joins[] = ' INNER JOIN subnet ON (INET_ATON(clientip) BETWEEN startaddr AND endaddr) ';
+ $args['lid'] = $this->argument;
+ $neg = $this->operator == '=' ? '' : 'NOT';
+ return "$neg (subnet.locationid = :lid OR machine.locationid = :lid)";
+ }
+ }
+}
+
+class SubnetFilter extends Filter
+{
+ public function __construct($operator, $argument) {
+ parent::__construct(null, $operator, $argument);
+ }
+ public function whereClause(&$args, &$joins) {
+ $argument = preg_replace('/[^0-9\.:]/', '', $this->argument);
+ return " clientip LIKE '$argument%'";
+ }
+}
+