From a2b5271835654c559850214b12ac0c9f6892de6f Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 14 Nov 2020 17:34:59 -0600 Subject: [PATCH] fix copy/paste typo --- web/ajax/frames.php | 638 ++++++++++++-------------------------------- 1 file changed, 173 insertions(+), 465 deletions(-) diff --git a/web/ajax/frames.php b/web/ajax/frames.php index 42f939128..e85988dbc 100644 --- a/web/ajax/frames.php +++ b/web/ajax/frames.php @@ -1,481 +1,189 @@ translate('ConjAnd'), - 'or' => translate('ConjOr') - ); - } - return $validConjunctionTypes; +if ( !canView('Events') ) $message = 'Insufficient permissions to view frames for user '.$user['Username']; + +// task must be set +if ( empty($_REQUEST['task']) ) { + $message = 'This request requires a task to be set'; +// query is the only supported task at the moment +} else if ( $_REQUEST['task'] != 'query' ) { + $message = 'Unrecognised task '.$_REQUEST['task']; + } else { + $task = $_REQUEST['task']; } +if ( empty($_REQUEST['eid']) ) { + $message = 'No event id supplied'; +} else { + $eid = validInt($_REQUEST['eid']); +} -class FilterTerm { - public $filter; - public $index; - public $attr; - public $op; - public $val; - public $values; - public $cnj; - public $obr; - public $cbr; +if ( $message ) { + ajaxError($message); + return; +} +// Search contains a user entered string to search on +$search = isset($_REQUEST['search']) ? $_REQUEST['search'] : ''; - public function __construct($filter = null, $term = NULL, $index=0) { - $this->filter = $filter; - $validConjunctionTypes = getFilterQueryConjunctionTypes(); +// Advanced search contains an array of "column name" => "search text" pairs +// Bootstrap table sends json_ecoded array, which we must decode +$advsearch = isset($_REQUEST['advsearch']) ? json_decode($_REQUEST['advsearch'], JSON_OBJECT_AS_ARRAY) : array(); - $this->index = $index; - $this->attr = $term['attr']; - $this->op = $term['op']; - $this->val = $term['val']; - if ( isset($term['cnj']) ) { - if ( array_key_exists($term['cnj'], $validConjunctionTypes) ) { - $this->cnj = $term['cnj']; - } else { - Warning('Invalid cnj ' . $term['cnj'].' in '.print_r($term, true)); - } - } +// Sort specifies the name of the column to sort on +$sort = 'FrameId'; +if ( isset($_REQUEST['sort']) ) { + $sort = $_REQUEST['sort']; +} - if ( isset($term['obr']) ) { - if ( (string)(int)$term['obr'] == $term['obr'] ) { - $this->obr = $term['obr']; - } else { - Warning('Invalid obr ' . $term['obr'] . ' in ' . print_r($term, true)); - } - } - if ( isset($term['cbr']) ) { - if ( (string)(int)$term['cbr'] == $term['cbr'] ) { - $this->cbr = $term['cbr']; - } else { - Warning('Invalid cbr ' . $term['cbr'] . ' in ' . print_r($term, true)); - } - } - } # end function __construct - - # Returns an array of values. AS term->value can be a list, we will break it apart, remove quotes etc - public function sql_values() { - $values = array(); - if ( !isset($this->val) ) { - Logger::Warning('No value in term'.$this->attr); - return $values; - } - - $vals = is_array($this->val) ? $this->val : preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $this->val)); - foreach ( $vals as $value ) { - - switch ( $this->attr ) { - - case 'AlarmedZoneId': - $value = '(SELECT * FROM Stats WHERE EventId=E.Id AND ZoneId='.$value.')'; - break; - case 'ExistsInFileSystem': - $value = ''; - break; - case 'DiskPercent': - $value = ''; - break; - case 'MonitorName': - case 'MonitorName': - case 'Name': - case 'Cause': - case 'Notes': - if ( strstr($this->op, 'LIKE') and ! strstr($this->val, '%' ) ) { - $value = '%'.$value.'%'; - } - $value = dbEscape($value); - break; - case 'MonitorServerId': - case 'FilterServerId': - case 'StorageServerId': - case 'ServerId': - if ( $value == 'ZM_SERVER_ID' ) { - $value = ZM_SERVER_ID; - } else if ( $value == 'NULL' ) { - - } else { - $value = dbEscape($value); - } - break; - case 'StorageId': - if ( $value != 'NULL' ) { - $value = dbEscape($value); - } - break; - case 'DateTime': - case 'StartDateTime': - case 'EndDateTime': - if ( $value != 'NULL' ) - $value = '\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\''; - break; - case 'Date': - case 'StartDate': - case 'EndDate': - if ( $value == 'CURDATE()' or $value == 'NOW()' ) { - $value = 'to_days('.$value.')'; - } else if ( $value != 'NULL' ) { - $value = 'to_days(\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')'; - } - break; - case 'Time': - case 'StartTime': - case 'EndTime': - if ( $value != 'NULL' ) - $value = 'extract(hour_second from \''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')'; - break; - default : - if ( $value == 'Odd' ) { - $value = 1; - } else if ( $value == 'Even' ) { - $value = 0; - } else if ( $value != 'NULL' ) - $value = dbEscape($value); - break; - } - $values[] = $value; - } // end foreach value - return $values; - } # end function sql_values - - public function sql_operator() { - switch ( $this->attr ) { - case 'AlarmZoneId': - return ' EXISTS '; - case 'ExistsInFileSystem': - case 'DiskPercent': - return ''; - } - - - switch ( $this->op ) { - case '=' : - case '!=' : - case '>=' : - case '>' : - case '<' : - case '<=' : - case 'LIKE' : - case 'NOT LIKE': - return ' '.$this->op.' '; - case '=~' : - return ' regexp '; - case '!~' : - return ' not regexp '; - case '=[]' : - case 'IN' : - return ' IN '; - case '![]' : - return ' NOT IN '; - case 'EXISTS' : - return ' EXISTS '; - case 'IS' : - # Odd will be replaced with 1 - # Even will be replaced with 0 - if ( $this->val == 'Odd' or $this->val == 'Even' ) { - return ' % 2 = '; - } else { - return ' IS '; - } - case 'IS NOT' : - if ( $this->val == 'Odd' or $this->val == 'Even' ) { - return ' % 2 = '; - } - return ' IS NOT '; - default: - Warning('Invalid operator in filter: ' . print_r($this->op, true)); - } // end switch op - } # end public function sql_operator - - /* Some terms don't have related SQL */ - public function sql() { - - $sql = ''; - if ( isset($this->cnj) ) { - $sql .= ' '.$this->cnj.' '; - } - if ( isset($this->obr) ) { - $sql .= ' '.str_repeat('(', $this->obr).' '; - } - - switch ( $this->attr ) { - case 'ExistsInFileSystem': - case 'DiskPercent': - $sql .= 'TRUE /*'.$this->attr.'*/'; - break; - case 'MonitorName': - $sql .= 'M.Name'; - break; - case 'ServerId': - case 'MonitorServerId': - $sql .= 'M.ServerId'; - break; - case 'StorageServerId': - $sql .= 'S.ServerId'; - break; - case 'FilterServerId': - $sql .= ZM_SERVER_ID; - break; - # Unspecified start or end, so assume start, this is to support legacy filters - case 'DateTime': - $sql .= 'E.StartDateTime'; - break; - case 'Date': - $sql .= 'to_days(E.StartDateTime)'; - break; - case 'Time': - $sql .= 'extract(hour_second FROM E.StartDateTime)'; - break; - case 'Weekday': - $sql .= 'weekday(E.StartDateTime)'; - break; - # Starting Time - case 'StartDateTime': - $sql .= 'E.StartDateTime'; - break; - case 'FrameId': - $sql .= 'Id'; - break; - case 'Type': - case 'TimeStamp': - case 'Delta': - case 'Score': - $sql .= $this->attr; - break; - case 'FramesEventId': - $sql .= 'F.EventId'; - break; - case 'StartDate': - $sql .= 'to_days(E.StartDateTime)'; - break; - case 'StartTime': - $sql .= 'extract(hour_second FROM E.StartDateTime)'; - break; - case 'StartWeekday': - $sql .= 'weekday(E.StartDateTime)'; - break; - # Ending Time - case 'EndDateTime': - $sql .= 'E.EndDateTime'; - break; - case 'EndDate': - $sql .= 'to_days(E.EndDateTime)'; - break; - case 'EndTime': - $sql .= 'extract(hour_second FROM E.EndDateTime)'; - break; - case 'EndWeekday': - $sql .= 'weekday(E.EndDateTime)'; - break; - case 'Emailed': - case 'Id': - case 'Name': - case 'DiskSpace': - case 'MonitorId': - case 'StorageId': - case 'SecondaryStorageId': - case 'Length': - case 'Frames': - case 'AlarmFrames': - case 'TotScore': - case 'AvgScore': - case 'MaxScore': - case 'Cause': - case 'Notes': - case 'StateId': - case 'Archived': - $sql .= 'E.'.$this->attr; - } - $sql .= $this->sql_operator(); - $values = $this->sql_values(); - if ( (count($values) > 1) or ($this->op == 'IN') or ($this->op == 'NOT IN') ) { - $sql .= '('.join(',', $values).')'; - } else { - $sql .= $values[0]; - } - - if ( isset($this->cbr) ) { - $sql .= ' '.str_repeat(')', $this->cbr).' '; - } - return $sql; - } # end public function sql - - public function querystring($objectname='filter', $querySep='&') { - # We don't validate the term parameters here - $query = ''; - if ( $this->cnj ) - $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cnj]').'='.$this->cnj; - if ( $this->obr ) - $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][obr]').'='.$this->obr; - - $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][attr]').'='.urlencode($this->attr); - $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][op]').'='.urlencode($this->op); - $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][val]').'='.urlencode($this->val); - if ( $this->cbr ) - $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cbr]').'='.$this->cbr; - return $query; - } # end public function querystring - - public function hidden_fields() { - $html =''; - if ( $this->cnj ) - $html .= ''.PHP_EOL; - - if ( $this->obr ) - $html .= ''.PHP_EOL; - - # attr should have been already validation, so shouldn't need htmlspecialchars - $html .= ''.PHP_EOL; - $html .= ''.PHP_EOL; - $html .= ''.PHP_EOL; - if ( $this->cbr ) - $html .= ''.PHP_EOL; - - return $html; - } # end public function hiddens_fields - - public function test($event=null) { - if ( !isset($event) ) { - # Is a Pre Condition - Debug("Testing " . $this->attr); - if ( $this->attr == 'DiskPercent' ) { - # The logic on this is really ugly. We are going to treat it as an OR - foreach ( $this->filter->get_StorageAreas() as $storage ) { - $string_to_eval = 'return $storage->disk_usage_percent() '.$this->op.' '.$this->val.';'; - try { - $ret = eval($string_to_eval); - Debug("Evalled $string_to_eval = $ret"); - if ( $ret ) - return true; - } catch ( Throwable $t ) { - Error('Failed evaluating '.$string_to_eval); - return false; - } - } # end foreach Storage Area - } else if ( $this->attr == 'SystemLoad' ) { - $string_to_eval = 'return getLoad() '.$this->op.' '.$this->val.';'; - try { - $ret = eval($string_to_eval); - Debug("Evaled $string_to_eval = $ret"); - if ( $ret ) - return true; - } catch ( Throwable $t ) { - Error('Failed evaluating '.$string_to_eval); - return false; - } - } else { - Error('testing unsupported pre term ' . $this->attr); - } - } else { - # Is a Post Condition - if ( $this->attr == 'ExistsInFileSystem' ) { - if ( - ($this->op == 'IS' and $this->val == 'True') - or - ($this->op == 'IS NOT' and $this->val == 'False') - ) { - return file_exists($event->Path()); - } else { - return !file_exists($event->Path()); - } - } else if ( $this->attr == 'DiskPercent' ) { - $string_to_eval = 'return $event->Storage()->disk_usage_percent() '.$this->op.' '.$this->val.';'; - try { - $ret = eval($string_to_eval); - Debug("Evalled $string_to_eval = $ret"); - if ( $ret ) - return true; - } catch ( Throwable $t ) { - Error('Failed evaluating '.$string_to_eval); - return false; - } - } else if ( $this->attr == 'DiskBlocks' ) { - $string_to_eval = 'return $event->Storage()->disk_usage_blocks() '.$this->op.' '.$this->val.';'; - try { - $ret = eval($string_to_eval); - Debug("Evalled $string_to_eval = $ret"); - if ( $ret ) - return true; - } catch ( Throwable $t ) { - Error('Failed evaluating '.$string_to_eval); - return false; - } - } else { - Error('testing unsupported post term ' . $this->attr); - } - } - return false; +// Offset specifies the starting row to return, used for pagination +$offset = 0; +if ( isset($_REQUEST['offset']) ) { + if ( ( !is_int($_REQUEST['offset']) and !ctype_digit($_REQUEST['offset']) ) ) { + ZM\Error('Invalid value for offset: ' . $_REQUEST['offset']); + } else { + $offset = $_REQUEST['offset']; } - - public function is_pre_sql() { - if ( $this->attr == 'DiskPercent' ) - return true; - if ( $this->attr == 'DiskBlocks' ) - return true; - return false; +} + +// Order specifies the sort direction, either asc or desc +$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC'; + +// Limit specifies the number of rows to return +$limit = 0; +if ( isset($_REQUEST['limit']) ) { + if ( ( !is_int($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) { + ZM\Error('Invalid value for limit: ' . $_REQUEST['limit']); + } else { + $limit = $_REQUEST['limit']; + } +} + +// +// MAIN LOOP +// + +// Only one supported task at the moment +switch ( $task ) { + case 'query' : + $data = queryRequest($eid, $search, $advsearch, $sort, $offset, $order, $limit); + break; + default : + ZM\Fatal("Unrecognised task '$task'"); +} // end switch task + +ajaxResponse($data); + +// +// FUNCTION DEFINITIONS +// + +function queryRequest($eid, $search, $advsearch, $sort, $offset, $order, $limit) { + + $data = array( + 'total' => 0, + 'totalNotFiltered' => 0, + 'rows' => array(), + 'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG) + ); + + // The names of the dB columns in the events table we are interested in + $columns = array('FrameId', 'Type', 'TimeStamp', 'Delta', 'Score'); + + if ( !in_array($sort, $columns) ) { + ZM\Error('Invalid sort field: ' . $sort); + $sort = 'FrameId'; } - public function is_post_sql() { - if ( $this->attr == 'ExistsInFileSystem' ) { - return true; + $Event = new ZM\Event($eid); + $Monitor = $Event->Monitor(); + $values = array(); + $likes = array(); + $where = 'WHERE EventId = '.$eid; + + $sql = 'SELECT * FROM `Frames` '.$where.' ORDER BY '.$sort.' '.$order; + + //ZM\Debug('Calling the following sql query: ' .$sql); + + $unfiltered_rows = array(); + $frame_ids = array(); + require_once('includes/Frame.php'); + foreach ( dbFetchAll($sql, NULL, $values) as $row ) { + $frame = new ZM\Frame($row); + $frame_ids[] = $frame->Id(); + $unfiltered_rows[] = $row; + } + + ZM\Debug('Have ' . count($unfiltered_rows) . ' frames matching base filter.'); + + $filtered_rows = null; + require_once('includes/Filter.php'); + if ( count($advsearch) or $search != '' ) { + $search_filter = new ZM\Filter(); + $search_filter = $search_filter->addTerm(array('cnj'=>'and', 'attr'=>'FrameId', 'op'=>'IN', 'val'=>$frame_ids)); + + // There are two search bars in the log view, normal and advanced + // Making an exuctive decision to ignore the normal search, when advanced search is in use + // Alternatively we could try to do both + if ( count($advsearch) ) { + $terms = array(); + foreach ( $advsearch as $col=>$text ) { + $terms[] = array('cnj'=>'and', 'attr'=>$col, 'op'=>'LIKE', 'val'=>$text); + } # end foreach col in advsearch + $terms[0]['obr'] = 1; + $terms[count($terms)-1]['cbr'] = 1; + $search_filter->addTerms($terms); + } else if ( $search != '' ) { + $search = '%' .$search. '%'; + $terms = array(); + foreach ( $columns as $col ) { + $terms[] = array('cnj'=>'or', 'attr'=>$col, 'op'=>'LIKE', 'val'=>$search); + } + $terms[0]['obr'] = 1; + $terms[0]['cnj'] = 'and'; + $terms[count($terms)-1]['cbr'] = 1; + $search_filter = $search_filter->addTerms($terms, array('obr'=>1, 'cbr'=>1, 'op'=>'OR')); + } # end if search + + $sql = 'SELECT * FROM `Frames` WHERE '.$search_filter->sql().' ORDER BY ' .$sort. ' ' .$order; + $filtered_rows = dbFetchAll($sql); + ZM\Debug('Have ' . count($filtered_rows) . ' frames matching search filter.'); + } else { + $filtered_rows = $unfiltered_rows; + } # end if search_filter->terms() > 1 + + $returned_rows = array(); + foreach ( array_slice($filtered_rows, $offset, $limit) as $row ) { + if ( ZM_WEB_LIST_THUMBS ) { + $base_img_src = '?view=image&fid=' .$row['Id']; + $ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth(); + $thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : ''; + $thmb_height = 'height="'.( ZM_WEB_LIST_THUMB_HEIGHT ? ZM_WEB_LIST_THUMB_HEIGHT : ZM_WEB_LIST_THUMB_WIDTH*$ratio_factor ) .'"'; + $thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$row['EventId']. '_' .$row['FrameId']. '.jpg'; + $img_src = join('&', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn))); + $full_img_src = join('&', array_filter(array($base_img_src, $thmb_fn))); + $frame_src = '?view=frame&eid=' .$row['EventId']. '&fid=' .$row['FrameId']; + + $row['Thumbnail'] = ''; } - return false; + $returned_rows[] = $row; + } # end foreach row matching search + + $data['rows'] = $returned_rows; + + # totalNotFiltered must equal total, except when either search bar has been used + $data['totalNotFiltered'] = count($unfiltered_rows); + if ( $search != '' || count($advsearch) ) { + $data['total'] = count($filtered_rows); + } else { + $data['total'] = $data['totalNotFiltered']; } - public static function is_valid_attr($attr) { - $attrs = array( - 'Score', - 'Delta', - 'TimeStamp', - 'Type', - 'FrameId', - 'EventId', - 'ExistsInFileSystem', - 'Emailed', - 'DiskSpace', - 'DiskPercent', - 'DiskBlocks', - 'MonitorName', - 'ServerId', - 'MonitorServerId', - 'StorageServerId', - 'FilterServerId', - 'DateTime', - 'Date', - 'Time', - 'Weekday', - 'StartDateTime', - 'FramesId', - 'FramesEventId', - 'StartDate', - 'StartTime', - 'StartWeekday', - 'EndDateTime', - 'EndDate', - 'EndTime', - 'EndWeekday', - 'Id', - 'Name', - 'MonitorId', - 'StorageId', - 'SecondaryStorageId', - 'Length', - 'Frames', - 'AlarmFrames', - 'TotScore', - 'AvgScore', - 'MaxScore', - 'Cause', - 'Notes', - 'StateId', - 'Archived' - ); - return in_array($attr, $attrs); - } -} # end class FilterTerm - -?> + return $data; +}