From 21a0a18055c266e129f351a5ac7a3bb5b6fc0a83 Mon Sep 17 00:00:00 2001 From: f0o Date: Wed, 22 Jun 2016 08:42:48 +0000 Subject: [PATCH] Fixed Device-Groups for multiple entries and glue-expansion --- includes/alerts.inc.php | 66 +--------------------------------- includes/common.php | 66 ++++++++++++++++++++++++++++++++++ includes/device-groups.inc.php | 47 ++++++++++++++++-------- 3 files changed, 100 insertions(+), 79 deletions(-) diff --git a/includes/alerts.inc.php b/includes/alerts.inc.php index 6af9c1181d..3e1da0b687 100644 --- a/includes/alerts.inc.php +++ b/includes/alerts.inc.php @@ -22,6 +22,7 @@ * @subpackage Alerts */ +include_once($config['install_dir'].'/includes/common.inc.php'); include_once($config['install_dir'].'/includes/device-groups.inc.php'); include_once($config['install_dir'].'/html/includes/authentication/'.$config['auth_mechanism'].'.inc.php'); @@ -88,71 +89,6 @@ function GenSQL($rule) { return $sql; } -/** - * Create a glue-chain - * @param array $tables Initial Tables to construct glue-chain - * @param string $target Glue to find (usual device_id) - * @param int $x Recursion Anchor - * @param array $hist History of processed tables - * @param array $last Glues on the fringe - * @return string|boolean - */ -function ResolveGlues($tables,$target,$x=0,$hist=array(),$last=array()) { - if( sizeof($tables) == 1 && $x != 0 ) { - if( dbFetchCell('SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_NAME = ? && COLUMN_NAME = ?',array($tables[0],$target)) == 1 ) { - return array_merge($last,array($tables[0].'.'.$target)); - } - else { - return false; - } - } - else { - $x++; - if( $x > 30 ) { - //Too much recursion. Abort. - return false; - } - foreach( $tables as $table ) { - $glues = dbFetchRows('SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME = ? && COLUMN_NAME LIKE "%\_id"',array($table)); - if( sizeof($glues) == 1 && $glues[0]['COLUMN_NAME'] != $target ) { - //Search for new candidates to expand - $ntables = array(); - list($tmp) = explode('_',$glues[0]['COLUMN_NAME'],2); - $ntables[] = $tmp; - $ntables[] = $tmp.'s'; - $tmp = dbFetchRows('SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME LIKE "'.substr($table,0,-1).'_%" && TABLE_NAME != "'.$table.'"'); - foreach( $tmp as $expand ) { - $ntables[] = $expand['TABLE_NAME']; - } - $tmp = ResolveGlues($ntables,$target,$x++,array_merge($tables,$ntables),array_merge($last,array($table.'.'.$glues[0]['COLUMN_NAME']))); - if( is_array($tmp) ) { - return $tmp; - } - } - else { - foreach( $glues as $glue ) { - if( $glue['COLUMN_NAME'] == $target ) { - return array_merge($last,array($table.'.'.$target)); - } - else { - list($tmp) = explode('_',$glue['COLUMN_NAME']); - $tmp .= 's'; - if( !in_array($tmp,$tables) && !in_array($tmp,$hist) ) { - //Expand table - $tmp = ResolveGlues(array($tmp),$target,$x++,array_merge($tables,array($tmp)),array_merge($last,array($table.'.'.$glue['COLUMN_NAME']))); - if( is_array($tmp) ) { - return $tmp; - } - } - } - } - } - } - } - //You should never get here. - return false; -} - /** * Process Macros * @param string $rule Rule to process diff --git a/includes/common.php b/includes/common.php index 1a7c817b8f..c9fc55ddfc 100644 --- a/includes/common.php +++ b/includes/common.php @@ -1234,3 +1234,69 @@ function get_port_id ($ports_mapped, $port, $port_association_mode) { return $port_id; } + +/** + * Create a glue-chain + * @param array $tables Initial Tables to construct glue-chain + * @param string $target Glue to find (usual device_id) + * @param int $x Recursion Anchor + * @param array $hist History of processed tables + * @param array $last Glues on the fringe + * @return string|boolean + */ +function ResolveGlues($tables,$target,$x=0,$hist=array(),$last=array()) { + if( sizeof($tables) == 1 && $x != 0 ) { + if( dbFetchCell('SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_NAME = ? && COLUMN_NAME = ?',array($tables[0],$target)) == 1 ) { + return array_merge($last,array($tables[0].'.'.$target)); + } + else { + return false; + } + } + else { + $x++; + if( $x > 30 ) { + //Too much recursion. Abort. + return false; + } + foreach( $tables as $table ) { + $glues = dbFetchRows('SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME = ? && COLUMN_NAME LIKE "%\_id"',array($table)); + if( sizeof($glues) == 1 && $glues[0]['COLUMN_NAME'] != $target ) { + //Search for new candidates to expand + $ntables = array(); + list($tmp) = explode('_',$glues[0]['COLUMN_NAME'],2); + $ntables[] = $tmp; + $ntables[] = $tmp.'s'; + $tmp = dbFetchRows('SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME LIKE "'.substr($table,0,-1).'_%" && TABLE_NAME != "'.$table.'"'); + foreach( $tmp as $expand ) { + $ntables[] = $expand['TABLE_NAME']; + } + $tmp = ResolveGlues($ntables,$target,$x++,array_merge($tables,$ntables),array_merge($last,array($table.'.'.$glues[0]['COLUMN_NAME']))); + if( is_array($tmp) ) { + return $tmp; + } + } + else { + foreach( $glues as $glue ) { + if( $glue['COLUMN_NAME'] == $target ) { + return array_merge($last,array($table.'.'.$target)); + } + else { + list($tmp) = explode('_',$glue['COLUMN_NAME']); + $tmp .= 's'; + if( !in_array($tmp,$tables) && !in_array($tmp,$hist) ) { + //Expand table + $tmp = ResolveGlues(array($tmp),$target,$x++,array_merge($tables,array($tmp)),array_merge($last,array($table.'.'.$glue['COLUMN_NAME']))); + if( is_array($tmp) ) { + return $tmp; + } + } + } + } + } + } + } + //You should never get here. + return false; +} + diff --git a/includes/device-groups.inc.php b/includes/device-groups.inc.php index c4651e59ee..a77ea0c0bb 100644 --- a/includes/device-groups.inc.php +++ b/includes/device-groups.inc.php @@ -25,6 +25,7 @@ * @subpackage Devices */ +include_once($config['install_dir'].'/includes/common.inc.php'); /** * Add a new device group @@ -97,26 +98,44 @@ function GenGroupSQL($pattern, $search='',$extra=0) { $pattern = rtrim($pattern, '||'); $tables = array_keys(array_flip($tables)); - $x = sizeof($tables); - $i = 0; - $join = ''; - while ($i < $x) { - if (isset($tables[($i + 1)])) { - $join .= $tables[$i].'.device_id = '.$tables[($i + 1)].'.device_id && '; + if( dbFetchCell('SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_NAME = ? && COLUMN_NAME = ?',array($tables[0],'device_id')) != 1 ) { + //Our first table has no valid glue, append the 'devices' table to it! + array_unshift($tables, 'devices'); + } + $x = sizeof($tables)-1; + $i = 0; + $join = ""; + while( $i < $x ) { + if( isset($tables[$i+1]) ) { + $gtmp = ResolveGlues(array($tables[$i+1]),'device_id'); + if( $gtmp === false ) { + //Cannot resolve glue-chain. Rule is invalid. + return false; + } + $last = ""; + $qry = ""; + foreach( $gtmp as $glue ) { + if( empty($last) ) { + list($tmp,$last) = explode('.',$glue); + $qry .= $glue.' = '; + } + else { + list($tmp,$new) = explode('.',$glue); + $qry .= $tmp.'.'.$last.' && '.$tmp.'.'.$new.' = '; + $last = $new; + } + if( !in_array($tmp, $tables) ) { + $tables[] = $tmp; + } + } + $join .= "( ".$qry.$tables[0].".device_id ) && "; } - $i++; } - - if (!empty($search)) { - $search .= ' &&'; - } - - $sql_extra = ''; if ($extra === 1) { $sql_extra = ",`devices`.*"; } - $sql = 'SELECT DISTINCT('.str_replace('(', '', $tables[0]).'.device_id)'.$sql_extra.' FROM '.implode(',', $tables).' WHERE '.$search.' ('.str_replace(array('%', '@', '!~', '~'), array('', '.*', 'NOT REGEXP', 'REGEXP'), $pattern).')'; + $sql = 'SELECT DISTINCT('.str_replace('(', '', $tables[0]).'.device_id)'.$sql_extra.' FROM '.implode(',', $tables).' WHERE ('.$join.''.str_replace("(","",$tables[0]).'.device_id = ?) && '.$search.' ('.str_replace(array('%', '@', '!~', '~'), array('', '.*', 'NOT REGEXP', 'REGEXP'), $pattern).')'; return $sql; }//end GenGroupSQL()