From a118e52f306b4825497ced695c8e6d6b3edd0efa Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 28 Sep 2020 16:13:06 -0400 Subject: [PATCH 001/169] Add 2>&1 to ffmpeg command line to get stderr as well --- web/views/image.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/web/views/image.php b/web/views/image.php index ff26682c7..58d37989b 100644 --- a/web/views/image.php +++ b/web/views/image.php @@ -242,17 +242,21 @@ if ( empty($_REQUEST['path']) ) { header('HTTP/1.0 404 Not Found'); ZM\Fatal("Can't create frame images from video because there is no video file for this event at (".$Event->Path().'/'.$Event->DefaultVideo() ); } - $command = ZM_PATH_FFMPEG.' -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -frames:v 1 '.$path; + $command = ZM_PATH_FFMPEG.' -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -frames:v 1 '.$path . ' 2>&1'; #$command ='ffmpeg -ss '. $Frame->Delta() .' -i '.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path; #$command ='ffmpeg -v 0 -i '.$Storage->Path().'/'.$Event->Path().'/'.$Event->DefaultVideo().' -vf "select=gte(n\\,'.$Frame->FrameId().'),setpts=PTS-STARTPTS" '.$path; ZM\Logger::Debug("Running $command"); $output = array(); $retval = 0; - exec( $command, $output, $retval ); + exec($command, $output, $retval); ZM\Logger::Debug("Command: $command, retval: $retval, output: " . implode("\n", $output)); - if ( ! file_exists( $path ) ) { + if ( ! file_exists($path) ) { header('HTTP/1.0 404 Not Found'); - ZM\Fatal('Can\'t create frame images from video for this event '.$Event->DefaultVideo() ); + ZM\Fatal('Can\'t create frame images from video for this event '.$Event->DefaultVideo().' + +Command was: '.$command.' + +Output was: '.implode(PHP_EOL,$output) ); } # Generating an image file will use up more disk space, so update the Event record. $Event->DiskSpace(null); From 26636e11720904d0e53c7de4439f110d7ad3ffad Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 28 Sep 2020 16:13:56 -0400 Subject: [PATCH 002/169] calculate thumb height based on ratio for frames --- web/skins/classic/views/frames.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/frames.php b/web/skins/classic/views/frames.php index c29160549..7afc96a7d 100644 --- a/web/skins/classic/views/frames.php +++ b/web/skins/classic/views/frames.php @@ -181,8 +181,9 @@ if ( count($frames) ) { Id(); + $ratio_factor = $Monitor->ViewHeight() / $Monitor->ViewWidth(); $thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : ''; - $thmb_height = ZM_WEB_LIST_THUMB_HEIGHT ? 'height='.ZM_WEB_LIST_THUMB_HEIGHT : ''; + $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(). '_' .$frame['EventId']. '_' .$frame['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))); From cc24df95933ca22effad1e0ec56680109846b54c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 8 Oct 2020 16:46:30 -0400 Subject: [PATCH 003/169] init shared_data in the purpose=QUERY case to prevent crash. Also don't load zones if we don't need them --- src/zm_monitor.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 31ece8a0e..260e11ead 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -492,6 +492,8 @@ Monitor::Monitor( shared_data->last_read_time = 0; shared_data->alarm_x = -1; shared_data->alarm_y = -1; + } else { + shared_data = nullptr; } if ( ( ! mem_ptr ) || ! shared_data->valid ) { @@ -2103,7 +2105,6 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) { } else { v4l_captures_per_frame = config.captures_per_frame; } - Debug(1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame); col++; std::string protocol = dbrow[col] ? dbrow[col] : ""; col++; @@ -2372,10 +2373,13 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) { 0 ); camera->setMonitor(monitor); - Zone **zones = 0; - int n_zones = Zone::Load(monitor, zones); - monitor->AddZones(n_zones, zones); - monitor->AddPrivacyBitmask(zones); + int n_zones = 0; + if ( load_zones ) { + Zone **zones = 0; + n_zones = Zone::Load(monitor, zones); + monitor->AddZones(n_zones, zones); + monitor->AddPrivacyBitmask(zones); + } Debug(1, "Loaded monitor %d(%s), %d zones", id, name, n_zones); return monitor; } // end Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) From df2f5f814b3bfb716f05c303b2fffb6d194124df Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 8 Oct 2020 15:50:12 -0400 Subject: [PATCH 004/169] fix case in mocord where cause would not contain motion --- src/zm_monitor.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 260e11ead..24a50488d 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1458,11 +1458,12 @@ bool Monitor::Analyse() { } if ( last_motion_score ) { score += last_motion_score; - if ( !event ) { + // cause is calculated every frame, + //if ( !event ) { if ( cause.length() ) cause += ", "; cause += MOTION_CAUSE; - } + //} noteSetMap[MOTION_CAUSE] = zoneSet; } // end if motion_score //shared_data->active = signal; // unneccessary active gets set on signal change @@ -1560,7 +1561,7 @@ bool Monitor::Analyse() { alarm_cause = alarm_cause + "," + std::string(zones[i]->Label()); } } - if ( !alarm_cause.empty() ) alarm_cause[0] = ' '; + if ( !alarm_cause.empty() ) alarm_cause[0] = ' '; // replace leading , with a space alarm_cause = cause + alarm_cause; strncpy(shared_data->alarm_cause, alarm_cause.c_str(), sizeof(shared_data->alarm_cause)-1); Info("%s: %03d - Gone into alarm state PreAlarmCount: %u > AlarmFrameCount:%u Cause:%s", From eefbed04c19c8d8bdea505a01c091be7d3c95869 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 5 Oct 2020 12:11:39 -0400 Subject: [PATCH 005/169] Add debugging for min_section_length keeping us in ALERT --- src/zm_monitor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 24a50488d..0bc8a8ac0 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1451,8 +1451,8 @@ bool Monitor::Analyse() { int new_motion_score = DetectMotion(*snap_image, zoneSet); Debug(3, - "After motion detection, last_motion_score(%d), new motion score(%d)", - last_motion_score, new_motion_score + "After motion detection, score(%d), last_motion_score(%d), new motion score(%d)", + score, last_motion_score, new_motion_score ); last_motion_score = new_motion_score; } @@ -1668,6 +1668,8 @@ bool Monitor::Analyse() { } else { shared_data->state = state = TAPE; } + } else { + Debug(1, "Not leaving ALERT beacuse image_count(%d)-last_alarm_count(%d) > post_event_count(%d) and timestamp.tv_sec(%d) - recording.tv_src(%d) >= min_section_length(%d)", image_count, last_alarm_count, post_event_count, timestamp->tv_sec, video_store_data->recording.tv_sec, min_section_length); } } // end if ALARM or ALERT From 617a1faa99fdc1635ac6f1809d7c5fdbef28ba34 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 5 Oct 2020 09:19:48 -0400 Subject: [PATCH 006/169] Add pre-alarm frames when alarm_frame_count > 1 and prealarmcount=0 --- src/zm_monitor.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 0bc8a8ac0..b66341beb 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1633,8 +1633,17 @@ bool Monitor::Analyse() { } } event->AddFrames(pre_event_images, images, timestamps); - } - if ( alarm_frame_count ) { + } else if ( alarm_frame_count > 1 ) { + int temp_alarm_frame_count = alarm_frame_count; + while ( --temp_alarm_frame_count ) { + Debug(1, "Adding previous frame due to alarm_frame_count %d", pre_index); + event->AddFrame(image_buffer[pre_index].image, *image_buffer[pre_index].timestamp, 0, nullptr); + pre_index = (pre_index + 1)%image_buffer_count; + } + } // end if pre_event_images + + if ( ( alarm_frame_count > 1 ) && Event::PreAlarmCount() ) { + Debug(1, "alarm frame count so SavePreAlarmFrames"); event->SavePreAlarmFrames(); } } From 080557d580a9d22f81a7162f6f9bd0007eb7159a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 19 Oct 2020 14:27:43 -0400 Subject: [PATCH 007/169] add an id to buttons div so that we can use it when calling scaleToFit --- web/skins/classic/views/cycle.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/cycle.php b/web/skins/classic/views/cycle.php index dd12b0fa3..745cec755 100644 --- a/web/skins/classic/views/cycle.php +++ b/web/skins/classic/views/cycle.php @@ -170,7 +170,7 @@ xhtmlHeaders(__FILE__, translate('CycleWatch')); ?> -
+
From 127ef9a130861b52acc385bd7da3dfcbefb29baa Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 19 Oct 2020 14:28:02 -0400 Subject: [PATCH 008/169] Fix scaling when using ScaleToFit --- web/skins/classic/views/js/cycle.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/views/js/cycle.js b/web/skins/classic/views/js/cycle.js index 6d2c3bdd4..d4ae50d44 100644 --- a/web/skins/classic/views/js/cycle.js +++ b/web/skins/classic/views/js/cycle.js @@ -40,6 +40,8 @@ function cyclePrev() { function initCycle() { periodical_id = nextCycleView.periodical(cycleRefreshTimeout); + var scale = $j('#scale').val(); + if ( scale == '0' || scale == 'auto' ) changeScale(); } function changeSize() { @@ -89,8 +91,6 @@ function changeScale() { Cookie.write('zmCycleScale', scale, {duration: 10*365}); Cookie.write('zmCycleWidth', 'auto', {duration: 10*365}); Cookie.write('zmCycleHeight', 'auto', {duration: 10*365}); - var newWidth = ( monitorData[monIdx].width * scale ) / SCALE_BASE; - var newHeight = ( monitorData[monIdx].height * scale ) / SCALE_BASE; // Scale the frame monitor_frame = $j('#imageFeed'); @@ -100,6 +100,8 @@ function changeScale() { } if ( scale != '0' && scale != '' && scale != 'auto' ) { + var newWidth = ( monitorData[monIdx].width * scale ) / SCALE_BASE; + var newHeight = ( monitorData[monIdx].height * scale ) / SCALE_BASE; if ( newWidth ) { monitor_frame.css('width', newWidth+'px'); } @@ -107,8 +109,13 @@ function changeScale() { monitor_frame.css('height', newHeight+'px'); } } else { - monitor_frame.css('width', '100%'); - monitor_frame.css('height', 'auto'); + //var bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus'); + var newSize = scaleToFit(monitorData[monIdx].width, monitorData[monIdx].height, monitor_frame, $j('#buttons')); + newWidth = newSize.width; + newHeight = newSize.height; + autoScale = newSize.autoScale; + monitor_frame.width(newWidth); + monitor_frame.height(newHeight); } /*Stream could be an applet so can't use moo tools*/ @@ -124,6 +131,7 @@ function changeScale() { //src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) )); src = src.replace(/scale=[\.\d]+/i, 'scale='+scale); + // zms doesn't actually use width&height if ( scale != '0' && scale != '' && scale != 'auto' ) { src = src.replace(/width=[\.\d]+/i, 'width='+newWidth); src = src.replace(/height=[\.\d]+/i, 'height='+newHeight); From 0e638745332513412bbddeae9d98a963d1eaf89b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 19 Oct 2020 14:28:21 -0400 Subject: [PATCH 009/169] fix calling changeScale when scale is 0 instead of auto --- web/skins/classic/views/js/watch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 19f74333b..ed4f370ae 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -848,7 +848,7 @@ function initPage() { if ( refreshApplet && appletRefreshTime ) { appletRefresh.delay(appletRefreshTime*1000); } - if ( scale == 'auto' ) changeScale(); + if ( scale == 'auto' || scale == '0' ) changeScale(); if ( window.history.length == 1 ) { $j('#closeControl').html(''); } @@ -858,7 +858,7 @@ function initPage() { } else if ( monitorRefresh > 0 ) { setInterval(reloadWebSite, monitorRefresh*1000); } -} +} // initPage // Kick everything off window.addEventListener('DOMContentLoaded', initPage); From 8a6aaa019f8abeb693fbeaa6b12a800911223c5d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 19 Oct 2020 14:29:18 -0400 Subject: [PATCH 010/169] Bump version for release to 1.34.22 --- distros/redhat/zoneminder.spec | 2 +- version | 2 +- web/skins/classic/css/base/views/cycle.css | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 web/skins/classic/css/base/views/cycle.css diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index d602ec855..e0de33c96 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -28,7 +28,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.34.21 +Version: 1.34.22 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/version b/version index 63a880485..9bda6b214 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.34.21 +1.34.22 diff --git a/web/skins/classic/css/base/views/cycle.css b/web/skins/classic/css/base/views/cycle.css new file mode 100644 index 000000000..9d89bc4b3 --- /dev/null +++ b/web/skins/classic/css/base/views/cycle.css @@ -0,0 +1,3 @@ +#imageFeed { + margin: 0 auto; +} From b950962f98a94329ab722c32f3bd7880ad1e8ba0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Oct 2020 19:21:15 -0400 Subject: [PATCH 011/169] Revert WEB_EVENT_SORT_FIELD change from StartTime to StartDateTime back to StartTime. StartTime is the column name. --- scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 43fbcb457..98ed7fa69 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -2648,7 +2648,7 @@ our @options = ( }, { name => 'ZM_WEB_EVENT_SORT_FIELD', - default => 'StartDateTime', + default => 'StartTime', description => 'Default field the event lists are sorted by', help => q` Events in lists can be initially ordered in any way you want. @@ -2660,7 +2660,7 @@ our @options = ( `, type => { db_type =>'string', - hint =>'Id|Name|Cause|DiskSpace|MonitorName|StartDateTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore', + hint =>'Id|Name|Cause|DiskSpace|MonitorName|StartTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore', pattern =>qr|.|, format =>q( $1 ) }, From d88fd5e4e0814853963010fd97ddf38006498265 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 20 Oct 2020 19:23:03 -0400 Subject: [PATCH 012/169] Revert WEB_EVENT_SORT_FIELD change from StartTime to StartDateTime back to StartTime. StartTime is the column name. --- web/skins/classic/views/filter.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index c19e06ef7..96e0b9728 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -366,6 +366,7 @@ for ( $i=0; $i < count($terms); $i++ ) { translate('AttrId'), 'Name' => translate('AttrName'), @@ -373,7 +374,7 @@ $sort_fields = array( 'DiskSpace' => translate('AttrDiskSpace'), 'Notes' => translate('AttrNotes'), 'MonitorName' => translate('AttrMonitorName'), - 'StartDateTime' => translate('AttrStartDateTime'), + 'StartTime' => translate('AttrStartDateTime'), 'Length' => translate('AttrDuration'), 'Frames' => translate('AttrFrames'), 'AlarmFrames' => translate('AttrAlarmFrames'), @@ -381,7 +382,7 @@ $sort_fields = array( 'AvgScore' => translate('AttrAvgScore'), 'MaxScore' => translate('AttrMaxScore'), ); -echo htmlSelect( 'filter[Query][sort_field]', $sort_fields, $filter->sort_field() ); +echo htmlSelect('filter[Query][sort_field]', $sort_fields, $filter->sort_field()); $sort_dirns = array( '1' => translate('SortAsc'), '0' => translate('SortDesc') From 34ce3a1498baa8332ac7053cea2e3cf9cef67ae1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Oct 2020 10:36:40 -0400 Subject: [PATCH 013/169] Use Filter::parse instead of parseFilter. Use Filter->addTerm to limit to User's monitor restrictions. Return early with better logging in the event of error. Introduce Filter->addTerm --- web/ajax/status.php | 23 +++++++++++++++-------- web/includes/Filter.php | 31 ++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/web/ajax/status.php b/web/ajax/status.php index 54b75b7a3..8d3d507c7 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -416,35 +416,42 @@ function getNearEvents() { $event = dbFetchOne('SELECT * FROM Events WHERE Id=?', NULL, array($eventId)); if ( !$event ) return $NearEvents; - parseFilter($_REQUEST['filter']); + $filter = ZM\Filter::parse($_REQUEST['filter']); parseSort(); - - if ( $user['MonitorIds'] ) - $midSql = ' AND MonitorId IN ('.join( ',', preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).')'; - else - $midSql = ''; + if ( $user['MonitorIds'] ) { + $filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds'])); + } # When listing, it may make sense to list them in descending order. But when viewing Prev should timewise earlier and Next should be after. if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartTime' ) { $sortOrder = 'ASC'; } - $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\''.$_REQUEST['filter']['sql'].$midSql.' AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC'); + $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\' AND ('.$filter->sql().') AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC'); if ( $sortColumn != 'E.Id' ) { # When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id $sql .= ', E.Id DESC'; } $sql .= ' LIMIT 1'; $result = dbQuery($sql); + if ( !$result ) { + ZM\Error("Failed to load previous event using $sql"); + return $NearEvents; + } + $prevEvent = dbFetchNext($result); - $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql.' AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC'); + $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."' AND (".$filter->sql().') AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC'); if ( $sortColumn != 'E.Id' ) { # When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id $sql .= ', E.Id ASC'; } $sql .= ' LIMIT 1'; $result = dbQuery($sql); + if ( !$result ) { + ZM\Error("Failed to load next event using $sql"); + return $NearEvents; + } $nextEvent = dbFetchNext($result); if ( $prevEvent ) { diff --git a/web/includes/Filter.php b/web/includes/Filter.php index 86c72692b..510717544 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -40,6 +40,7 @@ class Filter extends ZM_Object { public function sql() { if ( ! isset($this->_sql) ) { + $this->_sql = ''; foreach ( $this->FilterTerms() as $term ) { #if ( ! ($term->is_pre_sql() or $term->is_post_sql()) ) { $this->_sql .= $term->sql(); @@ -53,6 +54,7 @@ class Filter extends ZM_Object { public function querystring($separator='&') { if ( (! isset($this->_querystring)) or ( $separator != '&' ) ) { + $this->_querystring = ''; foreach ( $this->FilterTerms() as $term ) { $this->_querystring .= $term->querystring($separator); } # end foreach term @@ -65,6 +67,7 @@ class Filter extends ZM_Object { public function hidden_fields() { if ( ! isset($this->_hidden_fields) ) { + $this->_hidden_fields = ''; foreach ( $this->FilterTerms() as $term ) { $this->_hidden_fields .= $term->hidden_fields(); } # end foreach term @@ -141,6 +144,13 @@ class Filter extends ZM_Object { if ( func_num_args( ) ) { $this->{'Query'} = func_get_arg(0); $this->{'Query_json'} = jsonEncode($this->{'Query'}); + # We have altered the query so need to reset all the calculated results. + unset($this->_querystring); + unset($this->_sql); + unset($this->_hidden_fields); + unset($this->_pre_sql_conditions); + unset($this->_post_sql_conditions); + unset($this->_Terms); } if ( !property_exists($this, 'Query') ) { if ( property_exists($this, 'Query_json') and $this->{'Query_json'} ) { @@ -619,6 +629,25 @@ class Filter extends ZM_Object { return array_pop($exprStack); } # end function tree -} # end class Filter + function addTerm($term=false, $position=null) { + $terms = $this->terms(); + + if ( (!isset($position)) or ($position > count($terms)) ) + $position = count($terms); + else if ( $position < 0 ) + $position = 0; + + if ( $term && ($position == 0) ) { + # if only 1 term, don't need AND or OR + unset($term['cnj']); + } + + array_splice($terms, $position, 0, array($term ? $term : array())); + $this->terms($terms); + + return $this; + } # end function addTerm + +} # end class Filter ?> From 1dfebc24b0410b0b8b1398fb7a444cd800d8acd3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Oct 2020 10:36:58 -0400 Subject: [PATCH 014/169] Fix ZM\ --- web/includes/FilterTerm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/FilterTerm.php b/web/includes/FilterTerm.php index 1f428fefa..fca0c9e20 100644 --- a/web/includes/FilterTerm.php +++ b/web/includes/FilterTerm.php @@ -185,7 +185,7 @@ class FilterTerm { } return ' IS NOT '; default: - ZM\Warning('Invalid operator in filter: ' . print_r($this->op, true)); + Warning('Invalid operator in filter: ' . print_r($this->op, true)); } // end switch op } # end public function sql_operator From 1c5e1619091d3b35135512d7039c5a064c792e1f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Oct 2020 10:37:06 -0400 Subject: [PATCH 015/169] quotes --- web/includes/auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/auth.php b/web/includes/auth.php index f7cf7ec82..0268b0018 100644 --- a/web/includes/auth.php +++ b/web/includes/auth.php @@ -248,7 +248,7 @@ function userFromSession() { if ( isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]) ) $user = getAuthUser($_SESSION['AuthHash'.$_SESSION['remoteAddr']]); else - ZM\Debug("No auth hash in session, there should have been"); + ZM\Debug('No auth hash in session, there should have been'); } else { # Need to refresh permissions and validate that the user still exists $sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?'; From 946a59ce8b4d3facf57c9a09aabbbde89f4c0956 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Oct 2020 10:37:39 -0400 Subject: [PATCH 016/169] add special case for sort_field being StartDateTime. This is not an event column and must be corrected to StartTime --- web/includes/functions.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/includes/functions.php b/web/includes/functions.php index 7a562ca38..40306e0ec 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -1006,12 +1006,15 @@ function parseSort($saveToSession=false, $querySep='&') { $sortColumn = 'E.StartTime'; break; case 'StartDateTime' : + // Fix for systems with EVENT_SORT_ORDER set to erroneous StartDateTime. + $_REQUEST['sort_field'] = 'StartTime'; $sortColumn = 'E.StartTime'; break; case 'EndTime' : $sortColumn = 'E.EndTime'; break; case 'EndDateTime' : + $_REQUEST['sort_field'] = 'EndTime'; $sortColumn = 'E.EndTime'; break; case 'Length' : From 8f8526c2f1075edc8751aa96b7a234857fdf1ee7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Oct 2020 10:38:42 -0400 Subject: [PATCH 017/169] add some debug to session garbage collection --- web/includes/session.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/includes/session.php b/web/includes/session.php index 2358567ba..34ce8b13c 100644 --- a/web/includes/session.php +++ b/web/includes/session.php @@ -144,7 +144,9 @@ class Session { } public function _gc($max) { // Calculate what is to be deemed old - $old = time() - $max; + $now = time(); + $old = $now - $max; + ZM\Debug('doing session gc ' . $now . '-' . $max. '='.$old); $sth = $this->db->prepare('DELETE * FROM Sessions WHERE access < :old'); $sth->bindParam(':old', $old, PDO::PARAM_INT); return $sth->execute() ? true : false; From e6f08959fa73e81d4b7f2df497ddb6e19999da19 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 21 Oct 2020 10:40:26 -0400 Subject: [PATCH 018/169] Fix use of result instead of NearEvents --- web/ajax/status.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/status.php b/web/ajax/status.php index 8d3d507c7..0bafe16e4 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -459,7 +459,7 @@ function getNearEvents() { $NearEvents['PrevEventStartTime'] = $prevEvent['StartTime']; $NearEvents['PrevEventDefVideoPath'] = getEventDefaultVideoPath($prevEvent['Id']); } else { - $NearEvents['PrevEventId'] = $result['PrevEventStartTime'] = $result['PrevEventDefVideoPath'] = 0; + $NearEvents['PrevEventId'] = $NearEvents['PrevEventStartTime'] = $NearEvents['PrevEventDefVideoPath'] = 0; } if ( $nextEvent ) { $NearEvents['NextEventId'] = $nextEvent['Id']; From 4a0ada53351f527279cceb040d41d9ff5eedac11 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 22 Oct 2020 08:52:54 -0400 Subject: [PATCH 019/169] improve logging of invalid task in ajax/log --- web/ajax/log.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index 9e6bd9585..c840267aa 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -8,7 +8,7 @@ if ( !canView('System') ) { // Only the query task is supported at the moment if ( !isset($_REQUEST['task']) or $_REQUEST['task'] != 'query' ) { - ajaxError('Unrecognised action'); + ajaxError('Unrecognised task '.(isset($_REQUEST['task'])?$_REQUEST['task']:'')); return; } // The table we want our data from From 9372b2ef8c0d43caa2fb0b93865b4d41b0485b1f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 22 Oct 2020 08:53:05 -0400 Subject: [PATCH 020/169] remove debug --- web/skins/classic/views/js/monitor.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/web/skins/classic/views/js/monitor.js b/web/skins/classic/views/js/monitor.js index d612e806e..75cb89707 100644 --- a/web/skins/classic/views/js/monitor.js +++ b/web/skins/classic/views/js/monitor.js @@ -105,7 +105,6 @@ function initPage() { document.querySelectorAll('input[name="newMonitor[MaxFPS]"]').forEach(function(el) { el.oninput = el.onclick = function(e) { if ( e.target.value ) { - console.log('showing'); $j('#newMonitor\\[MaxFPS\\]').show(); } else { $j('#newMonitor\\[MaxFPS\\]').hide(); @@ -115,7 +114,6 @@ function initPage() { document.querySelectorAll('input[name="newMonitor[AlarmMaxFPS]"]').forEach(function(el) { el.oninput = el.onclick = function(e) { if ( e.target.value ) { - console.log('showing'); $j('#newMonitor\\[AlarmMaxFPS\\]').show(); } else { $j('#newMonitor\\[AlarmMaxFPS\\]').hide(); @@ -209,7 +207,6 @@ function initPage() { var form = document.getElementById('contentForm'); var latitude = form.elements['newMonitor[Latitude]'].value; var longitude = form.elements['newMonitor[Longitude]'].value; - console.log("lat: " + latitude + ', long:'+longitude); map = L.map('LocationMap', { center: L.latLng(latitude, longitude), zoom: 13, @@ -258,13 +255,9 @@ function random_WebColour() { function update_estimated_ram_use() { var buffer_count = document.querySelectorAll('input[name="newMonitor[ImageBufferCount]"]')[0].value; - console.log(buffer_count); var width = document.querySelectorAll('input[name="newMonitor[Width]"]')[0].value; - console.log(width); var height = document.querySelectorAll('input[name="newMonitor[Height]"]')[0].value; - console.log(height); var colours = document.querySelectorAll('select[name="newMonitor[Colours]"]')[0].value; - console.log(colours); document.getElementById('estimated_ram_use').innerHTML = human_filesize(buffer_count * width * height * colours, 0); } From 0d14dcfbfac76ceb0b62fbfa91ab01e116d89475 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 22 Oct 2020 08:49:07 -0500 Subject: [PATCH 021/169] WIP events view server pagination --- web/skins/classic/views/events.php | 486 +++++++++++------------------ 1 file changed, 184 insertions(+), 302 deletions(-) diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index a70fa8d19..c8e033fc9 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -1,331 +1,213 @@ "search text" pairs +// Bootstrap table sends json_ecoded array, which we must decode +$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); + +// Sort specifies the name of the column to sort on +$sort = 'StartTime'; +if ( isset($_REQUEST['sort']) ) { + $sort = $_REQUEST['sort']; } -$filter = isset($_REQUEST['filter_id']) ? new ZM\Filter($_REQUEST['filter_id']) : new ZM\Filter(); -if ( isset($_REQUEST['filter'])) { - $filter->set($_REQUEST['filter']); -} - -parseSort(); - -$filterQuery = $filter->querystring(); -ZM\Debug('Filter '.print_r($filter, true)); - -if ( $filter->sql() ) { - $eventsSql .= ' AND ('.$filter->sql().')'; -} else { - ZM\Warning('No filters'); - exit; -} -$eventsSql .= ' ORDER BY '.$sortColumn.' '.$sortOrder; -if ( $sortColumn != 'E.Id' ) $eventsSql .= ',E.Id '.$sortOrder; - -$page = isset($_REQUEST['page']) ? validInt($_REQUEST['page']) : 0; -$limit = isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : $filter['limit']; - -if ( $_POST ) { - // I think this is basically so that a refresh doesn't repost - ZM\Debug('Redirecting to ' . $_SERVER['REQUEST_URI']); - header('Location: ?view=' . $view.htmlspecialchars_decode($filterQuery).htmlspecialchars_decode($sortQuery).$limitQuery.'&page='.$page); - exit(); -} - -$failed = !$filter->test_pre_sql_conditions(); -if ( $failed ) { - ZM\Debug('Pre conditions failed, not doing sql'); -} - -$results = $failed ? null : dbQuery($eventsSql); - -$nEvents = $results ? $results->rowCount() : 0; -if ( ! $results ) { - global $error_message; - $error_message = dbError($eventsSql); -} -ZM\Debug("Pre conditions succeeded sql return $nEvents events"); - -if ( !empty($limit) && ($nEvents > $limit) ) { - $nEvents = $limit; -} -$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE); -#Debug("Page $page Limit $limit #vents: $nEvents pages: $pages "); -if ( !empty($page) ) { - if ( $page < 0 ) - $page = 1; - else if ( $pages and ( $page > $pages ) ) - $page = $pages; - - $limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE); - if ( empty($limit) ) { - $limitAmount = ZM_WEB_EVENTS_PER_PAGE; +// 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 { - $limitLeft = $limit - $limitStart; - $limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft; + $offset = $_REQUEST['offset']; } - $eventsSql .= ' LIMIT '.$limitStart.', '.$limitAmount; -} else if ( !empty($limit) ) { - $eventsSql .= ' LIMIT 0, '.$limit; } -$maxShortcuts = 5; +// Order specifies the sort direction, either asc or desc +$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC'; -$focusWindow = true; - -$storage_areas = ZM\Storage::find(); -$StorageById = array(); -foreach ( $storage_areas as $S ) { - $StorageById[$S->Id()] = $S; +// Limit specifies the number of rows to return +$limit = 100; +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']; + } } -xhtmlHeaders(__FILE__, translate('Events')); -getBodyTopHTML(); +// +// MAIN LOOP +// -?> - -
- -
- - - - - - - - - - - -
+switch ( $task ) { + case 'archive' : + case 'unarchive' : + foreach ( $eids as $eid ) archiveRequest($task, $eid); + break; + case 'delete' : + foreach ( $eids as $eid ) $data[] = deleteRequest($eid); + break; + case 'query' : + $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit); + break; + default : + ZM\Fatal("Unrecognised task '$task'"); +} // end switch task - -
- - - - - - - - - - - - - - - - - - - - 1 ) { -?> - - - - - - - - - -test_post_sql_conditions($event) ) { - $event->remove_from_cache(); - continue; - } - $events[] = $event; - if ( $limit and (count($events) >= $limit) ) { - break; - } - ZM\Debug("Have " . count($events) . " events, limit $limit"); +function archiveRequest($task, $eid) { + $archiveVal = ($task == 'archive') ? 1 : 0; + dbQuery( + 'UPDATE Events SET Archived = ? WHERE Id = ?', + array($archiveVal, $eid) + ); +} + +function deleteRequest($eid) { + $message = array(); + $event = new ZM\Event($eid); + if ( !$event->Id() ) { + $message[] = array($eid=>'Event not found.'); + } else if ( $event->Archived() ) { + $message[] = array($eid=>'Event is archived, cannot delete it.'); + } else { + $event->delete(); } - foreach ( $events as $event ) { + + return $message; +} - $scale = max(reScale(SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE); -?> - Archived() ? ' class="archived"' : '' ?>> - - +function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { + // Put server pagination code here + // The table we want our data from + $table = 'Events'; - + // The names of the dB columns in the log table we are interested in + $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace'); - - - - - - - - - - - - - - 1 ) { -?> - - -DiskSpace(); -?> - -'; - $imgSrc = $event->getThumbnailSrc(array(),'&'); - $streamSrc = $event->getStreamSrc(array( - 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); - $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; - echo ''.$imgHtml.''; - echo ''; - } // end if ZM_WEB_LIST_THUMBS -?> - - - - - - - -1 ) { -?> - -$text ) { + if ( !in_array($col, array_merge($columns, $col_alt)) ) { + ZM\Error("'$col' is not a sortable column name"); + continue; + } + $text = '%' .$text. '%'; + array_push($likes, $col.' LIKE ?'); + array_push($query['values'], $text); + } + $wherevalues = $query['values']; + $where = ' WHERE (' .implode(' OR ', $likes). ')'; + + } else if ( $search != '' ) { + + $search = '%' .$search. '%'; + foreach ( $columns as $col ) { + array_push($likes, $col.' LIKE ?'); + array_push($query['values'], $search); + } + $wherevalues = $query['values']; + $where = ' WHERE (' .implode(' OR ', $likes). ')'; + } + + $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; + array_push($query['values'], $offset, $limit); + + ZM\Warning('Calling the following sql query: ' .$query['sql']); + + $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); + if ( $search != '' || count($advsearch) ) { + $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues); + } else { + $data['total'] = $data['totalNotFiltered']; + } + + $storage_areas = ZM\Storage::find(); + $StorageById = array(); + foreach ( $storage_areas as $S ) { + $StorageById[$S->Id()] = $S; + } + + $monitor_names = ZM\Monitor::find(); + $MonitorById = array(); + foreach ( $monitor_names as $S ) { + $MonitorById[$S->Id()] = $S; + } + + $rows = array(); + foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { + $event = new ZM\Event($row['Id']); + $scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width()); + $imgSrc = $event->getThumbnailSrc(array(),'&'); + $streamSrc = $event->getStreamSrc(array( + 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); + + // Modify the row data as needed + $row['imgHtml'] = '' .validHtmlStr('Event ' .$event->Id()). ''; + $row['Name'] = validHtmlStr($row['Name']); + $row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No'); + $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); + $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; + $row['Cause'] = validHtmlStr($row['Cause']); + $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); + $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); + $row['Length'] = gmdate('H:i:s', $row['Length'] ); + $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; + $row['Notes'] = htmlspecialchars($row['Notes']); + $row['DiskSpace'] = human_filesize($row['DiskSpace']); + $rows[] = $row; + } + $data['rows'] = $rows; + $data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG); + + return $data; } ?> - - - - - - - - - -
-
- From 230f35f0c0a81c846a3841a3485c5262b615bfb1 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 22 Oct 2020 08:50:06 -0500 Subject: [PATCH 022/169] comment out debug in events.js --- web/skins/classic/views/js/events.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index f037795e8..29c77ceb7 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -247,7 +247,7 @@ function initPage() { } var selections = getIdSelections(); - console.log(selections); + //console.log(selections); evt.preventDefault(); $j.getJSON(thisUrl + '?request=events&task=unarchive&eids[]='+selections.join('&eids[]=')) From 6c546f36ae1cf7c5565a38b4750236722087a4d2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 22 Oct 2020 10:43:35 -0400 Subject: [PATCH 023/169] allow dashes and underscores in log file name --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 39c10a058..f6fb77c65 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -159,7 +159,7 @@ sub new { ( $this->{fileName} = $0 ) =~ s|^.*/||; $this->{logPath} = $ZoneMinder::Config::Config{ZM_PATH_LOGS}; $this->{logFile} = $this->{logPath}.'/'.$this->{id}.'.log'; - ($this->{logFile}) = $this->{logFile} =~ /^([\w\.\/]+)$/; + ($this->{logFile}) = $this->{logFile} =~ /^([_\-\w\.\/]+)$/; $this->{trace} = 0; @@ -210,7 +210,7 @@ sub initialise( @ ) { if ( my $logFile = $this->getTargettedEnv('LOG_FILE') ) { $tempLogFile = $logFile; } - ($tempLogFile) = $tempLogFile =~ /^([\w\.\/]+)$/; + ($tempLogFile) = $tempLogFile =~ /^([_\-\w\.\/]+)$/; my $tempLevel = INFO; my $tempTermLevel = $this->{termLevel}; From 40c57b4b238a882456125fc67132cfd801bd13eb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 22 Oct 2020 10:43:53 -0400 Subject: [PATCH 024/169] Improve logic in set, improve logging --- scripts/ZoneMinder/lib/ZoneMinder/Object.pm | 54 +++++++++------------ 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Object.pm b/scripts/ZoneMinder/lib/ZoneMinder/Object.pm index 569b3de9d..b262b6f85 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Object.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Object.pm @@ -40,6 +40,10 @@ our @ISA = qw(ZoneMinder::Base); # # ========================================================================== +sub def_or_undef { + return defined($_[0]) ? $_[0] : 'undef'; +} + use ZoneMinder::Config qw(:all); use ZoneMinder::Logger qw(:all); use ZoneMinder::Database qw(:all); @@ -370,38 +374,27 @@ sub set { $log->error("$type -> set called with non-hash params from $caller $line"); } - foreach my $field ( keys %fields ) { - if ( $params ) { - $log->debug("field: $field, param: ".$$params{$field}) if $debug; - if ( exists $$params{$field} ) { - $log->debug("field: $field, $$self{$field} =? param: ".$$params{$field}) if $debug; - if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) { -# Only make changes to fields that have changed - if ( defined $fields{$field} ) { - $$self{$field} = $$params{$field} if defined $fields{$field}; - push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating - } # end if - $log->debug("Running $field with $$params{$field}") if $debug; - if ( my $func = $self->can( $field ) ) { - $func->( $self, $$params{$field} ); - } # end if - } # end if - } # end if - } # end if $params - - if ( defined $fields{$field} ) { - if ( $$self{$field} ) { - $$self{$field} = transform( $type, $field, $$self{$field} ); - } # end if $$self{field} - } - } # end foreach field + if ( $params ) { + foreach my $field ( keys %{$params} ) { + $log->debug("field: $field, ".def_or_undef($$self{$field}).' =? param: '.def_or_undef($$params{$field})) if $debug; + if ( ( ! defined $$self{$field} ) or ($$self{$field} ne $params->{$field}) ) { + # Only make changes to fields that have changed + if ( defined $fields{$field} ) { + $$self{$field} = $$params{$field}; + push @set_fields, $fields{$field}, $$params{$field}; #mark for sql updating + } # end if has a column + $log->debug("Running $field with $$params{$field}") if $debug; + if ( my $func = $self->can( $field ) ) { + $func->( $self, $$params{$field} ); + } # end if has function + } # end if has change + } # end foreach field + } # end if $params foreach my $field ( keys %defaults ) { - if ( ( ! exists $$self{$field} ) or (!defined $$self{$field}) or ( $$self{$field} eq '' ) ) { - $log->debug("Setting default ($field) ($$self{$field}) ($defaults{$field}) ") if $debug; + $log->debug("Setting default ($field) (".def_or_undef($$self{$field}).') ('.def_or_undef($defaults{$field}).') ') if $debug; if ( defined $defaults{$field} ) { - $log->debug("Default $field is defined: $defaults{$field}") if $debug; if ( $defaults{$field} eq 'NOW()' ) { $$self{$field} = 'NOW()'; } else { @@ -411,8 +404,9 @@ sub set { } else { $$self{$field} = $defaults{$field}; } # end if -#$$self{$field} = ( defined $defaults{$field} ) ? eval($defaults{$field}) : $defaults{$field}; - $log->debug("Setting default for ($field) using ($defaults{$field}) to ($$self{$field}) ") if $debug; + $log->debug("Setting default for ($field) using (".def_or_undef($defaults{$field}).') to ('.def_or_undef($$self{$field}).') ') if $debug; + } elsif ( defined $fields{$field} and $$self{$field} ) { + $$self{$field} = transform( $type, $field, $$self{$field} ); } # end if } # end foreach default return @set_fields; From d117e993ad96400e94d933c5af18a0a02d698b9b Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 22 Oct 2020 10:17:34 -0500 Subject: [PATCH 025/169] add create task to ajax/log.php --- web/ajax/log.php | 230 ++++++++++++++++++++++++++++++----------------- 1 file changed, 146 insertions(+), 84 deletions(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index c840267aa..bde07ed65 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -1,24 +1,27 @@ $text ) { - if ( !in_array($col, array_merge($columns, $col_alt)) ) { - ZM\Error("'$col' is not a sortable column name"); - continue; - } - $text = '%' .$text. '%'; - array_push($likes, $col.' LIKE ?'); - array_push($query['values'], $text); - } - $wherevalues = $query['values']; - $where = ' WHERE (' .implode(' OR ', $likes). ')'; - -} else if ( $search != '' ) { - - $search = '%' .$search. '%'; - foreach ( $columns as $col ) { - array_push($likes, $col.' LIKE ?'); - array_push($query['values'], $search); - } - $wherevalues = $query['values']; - $where = ' WHERE (' .implode(' OR ', $likes). ')'; -} - -$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; -array_push($query['values'], $offset, $limit); - -//ZM\Warning('Calling the following sql query: ' .$query['sql']); - -$data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); -if ( $search != '' || count($advsearch) ) { - $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues); -} else { - $data['total'] = $data['totalNotFiltered']; -} - -if ( !$Servers ) - $Servers = ZM\Server::find(); -$servers_by_Id = array(); -# There is probably a better way to do this. -foreach ( $Servers as $server ) { - $servers_by_Id[$server->Id()] = $server; -} - -$rows = array(); -foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { - $row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey'])); - $row['Server'] = ( $row['ServerId'] and isset($servers_by_Id[$row['ServerId']]) ) ? $servers_by_Id[$row['ServerId']]->Name() : ''; - // First strip out any html tags - // Second strip out all characters that are not ASCII 32-126 (yes, 126) - $row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message'])); - $rows[] = $row; -} -$data['rows'] = $rows; -$data['logstate'] = logState(); -$data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG); +switch ( $task ) { + case 'create' : + createRequest($task, $eid); + break; + case 'query' : + $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit); + break; + default : + ZM\Fatal('Unrecognised task '.$task); +} // end switch task ajaxResponse($data); +// +// FUNCTION DEFINITIONS +// + +function createRequest() { + if ( !empty($_POST['level']) && !empty($_POST['message']) ) { + ZM\logInit(array('id'=>'web_js')); + + $string = $_POST['message']; + + $file = !empty($_POST['file']) ? preg_replace('/\w+:\/\/[\w.:]+\//', '', $_POST['file']) : ''; + if ( !empty($_POST['line']) ) { + $line = validInt($_POST['line']); + } else { + $line = NULL; + } + + $levels = array_flip(ZM\Logger::$codes); + if ( !isset($levels[$_POST['level']]) ) { + ZM\Panic('Unexpected logger level '.$_POST['level']); + } + $level = $levels[$_POST['level']]; + ZM\Logger::fetch()->logPrint($level, $string, $file, $line); + } else { + ZM\Error('Invalid log create: '.print_r($_POST, true)); + } +} + +function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { + global $Servers; + + // The table we want our data from + $table = 'Logs'; + + // The names of the dB columns in the log table we are interested in + $columns = array('TimeKey', 'Component', 'ServerId', 'Pid', 'Code', 'Message', 'File', 'Line'); + + // The names of columns shown in the log view that are NOT dB columns in the database + $col_alt = array('DateTime', 'Server'); + + if ( !in_array($sort, array_merge($columns, $col_alt)) ) { + ZM\Error('Invalid sort field: ' . $sort); + return; + } + + $col_str = implode(', ', $columns); + $data = array(); + $query = array(); + $query['values'] = array(); + $likes = array(); + $where = ''; + // 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) ) { + + foreach ( $advsearch as $col=>$text ) { + if ( !in_array($col, array_merge($columns, $col_alt)) ) { + ZM\Error("'$col' is not a sortable column name"); + continue; + } + // Don't use wildcards on advanced search + //$text = '%' .$text. '%'; + array_push($likes, $col.' LIKE ?'); + array_push($query['values'], $text); + } + $wherevalues = $query['values']; + $where = ' WHERE (' .implode(' OR ', $likes). ')'; + + } else if ( $search != '' ) { + + $search = '%' .$search. '%'; + foreach ( $columns as $col ) { + array_push($likes, $col.' LIKE ?'); + array_push($query['values'], $search); + } + $wherevalues = $query['values']; + $where = ' WHERE (' .implode(' OR ', $likes). ')'; + } + + $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; + array_push($query['values'], $offset, $limit); + + //ZM\Warning('Calling the following sql query: ' .$query['sql']); + + $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); + if ( $search != '' || count($advsearch) ) { + $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues); + } else { + $data['total'] = $data['totalNotFiltered']; + } + + if ( !$Servers ) + $Servers = ZM\Server::find(); + $servers_by_Id = array(); + # There is probably a better way to do this. + foreach ( $Servers as $server ) { + $servers_by_Id[$server->Id()] = $server; + } + + $rows = array(); + foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { + $row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey'])); + $row['Server'] = ( $row['ServerId'] and isset($servers_by_Id[$row['ServerId']]) ) ? $servers_by_Id[$row['ServerId']]->Name() : ''; + // First strip out any html tags + // Second strip out all characters that are not ASCII 32-126 (yes, 126) + $row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message'])); + $rows[] = $row; + } + $data['rows'] = $rows; + $data['logstate'] = logState(); + $data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG); + + return $data; +} From a0f733615c6513bb5ef0d08b1e05b799e2cf63be Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 22 Oct 2020 11:26:34 -0400 Subject: [PATCH 026/169] allow empty string as a default value --- scripts/ZoneMinder/lib/ZoneMinder/Object.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Object.pm b/scripts/ZoneMinder/lib/ZoneMinder/Object.pm index b262b6f85..0f8bcb8ad 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Object.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Object.pm @@ -395,8 +395,8 @@ sub set { if ( ( ! exists $$self{$field} ) or (!defined $$self{$field}) or ( $$self{$field} eq '' ) ) { $log->debug("Setting default ($field) (".def_or_undef($$self{$field}).') ('.def_or_undef($defaults{$field}).') ') if $debug; if ( defined $defaults{$field} ) { - if ( $defaults{$field} eq 'NOW()' ) { - $$self{$field} = 'NOW()'; + if ( $defaults{$field} eq '' or $defaults{$field} eq 'NOW()' ) { + $$self{$field} = $defaults{$field}; } else { $$self{$field} = eval($defaults{$field}); $log->error( "Eval error of object default $field default ($defaults{$field}) Reason: " . $@ ) if $@; From 29819d8044c75f4c710ad4eff06723635a472b7a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 22 Oct 2020 13:27:47 -0500 Subject: [PATCH 027/169] fix copy/paste error with events.php --- web/ajax/events.php | 15 +- web/skins/classic/views/events.php | 484 ++++++++++++++++++----------- 2 files changed, 308 insertions(+), 191 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index f9a4fc14b..c8e033fc9 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -36,12 +36,7 @@ $advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_ // Sort specifies the name of the column to sort on $sort = 'StartTime'; if ( isset($_REQUEST['sort']) ) { - if ( !in_array($_REQUEST['sort'], array_merge($columns, $col_alt)) ) { - ZM\Error('Invalid sort field: ' . $_REQUEST['sort']); - } else { - $sort = $_REQUEST['sort']; - //if ( $sort == 'DateTime' ) $sort = 'TimeKey'; - } + $sort = $_REQUEST['sort']; } // Offset specifies the starting row to return, used for pagination @@ -122,9 +117,13 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { // The names of the dB columns in the log table we are interested in $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace'); - // The names of columns shown in the log view that are NOT dB columns in the database + // The names of columns shown in the event view that are NOT dB columns in the database $col_alt = array('Monitor', 'Storage'); + if ( !in_array($sort, array_merge($columns, $col_alt)) ) { + ZM\Fatal('Invalid sort field: ' . $sort); + } + $col_str = implode(', ', $columns); $data = array(); $query = array(); @@ -162,7 +161,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); - //ZM\Warning('Calling the following sql query: ' .$query['sql']); + ZM\Warning('Calling the following sql query: ' .$query['sql']); $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); if ( $search != '' || count($advsearch) ) { diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index c8e033fc9..a70fa8d19 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -1,213 +1,331 @@ "search text" pairs -// Bootstrap table sends json_ecoded array, which we must decode -$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); - -// Sort specifies the name of the column to sort on -$sort = 'StartTime'; -if ( isset($_REQUEST['sort']) ) { - $sort = $_REQUEST['sort']; +$eventsSql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultScale FROM Monitors AS M INNER JOIN Events AS E on (M.Id = E.MonitorId) WHERE'; +if ( $user['MonitorIds'] ) { + $user_monitor_ids = ' M.Id in ('.$user['MonitorIds'].')'; + $eventsSql .= $user_monitor_ids; +} else { + $eventsSql .= ' 1'; } -// 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']); +$filter = isset($_REQUEST['filter_id']) ? new ZM\Filter($_REQUEST['filter_id']) : new ZM\Filter(); +if ( isset($_REQUEST['filter'])) { + $filter->set($_REQUEST['filter']); +} + +parseSort(); + +$filterQuery = $filter->querystring(); +ZM\Debug('Filter '.print_r($filter, true)); + +if ( $filter->sql() ) { + $eventsSql .= ' AND ('.$filter->sql().')'; +} else { + ZM\Warning('No filters'); + exit; +} +$eventsSql .= ' ORDER BY '.$sortColumn.' '.$sortOrder; +if ( $sortColumn != 'E.Id' ) $eventsSql .= ',E.Id '.$sortOrder; + +$page = isset($_REQUEST['page']) ? validInt($_REQUEST['page']) : 0; +$limit = isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : $filter['limit']; + +if ( $_POST ) { + // I think this is basically so that a refresh doesn't repost + ZM\Debug('Redirecting to ' . $_SERVER['REQUEST_URI']); + header('Location: ?view=' . $view.htmlspecialchars_decode($filterQuery).htmlspecialchars_decode($sortQuery).$limitQuery.'&page='.$page); + exit(); +} + +$failed = !$filter->test_pre_sql_conditions(); +if ( $failed ) { + ZM\Debug('Pre conditions failed, not doing sql'); +} + +$results = $failed ? null : dbQuery($eventsSql); + +$nEvents = $results ? $results->rowCount() : 0; +if ( ! $results ) { + global $error_message; + $error_message = dbError($eventsSql); +} +ZM\Debug("Pre conditions succeeded sql return $nEvents events"); + +if ( !empty($limit) && ($nEvents > $limit) ) { + $nEvents = $limit; +} +$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE); +#Debug("Page $page Limit $limit #vents: $nEvents pages: $pages "); +if ( !empty($page) ) { + if ( $page < 0 ) + $page = 1; + else if ( $pages and ( $page > $pages ) ) + $page = $pages; + + $limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE); + if ( empty($limit) ) { + $limitAmount = ZM_WEB_EVENTS_PER_PAGE; } else { - $offset = $_REQUEST['offset']; + $limitLeft = $limit - $limitStart; + $limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft; } + $eventsSql .= ' LIMIT '.$limitStart.', '.$limitAmount; +} else if ( !empty($limit) ) { + $eventsSql .= ' LIMIT 0, '.$limit; } -// Order specifies the sort direction, either asc or desc -$order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC'; +$maxShortcuts = 5; -// Limit specifies the number of rows to return -$limit = 100; -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']; - } +$focusWindow = true; + +$storage_areas = ZM\Storage::find(); +$StorageById = array(); +foreach ( $storage_areas as $S ) { + $StorageById[$S->Id()] = $S; } -// -// MAIN LOOP -// +xhtmlHeaders(__FILE__, translate('Events')); +getBodyTopHTML(); -switch ( $task ) { - case 'archive' : - case 'unarchive' : - foreach ( $eids as $eid ) archiveRequest($task, $eid); - break; - case 'delete' : - foreach ( $eids as $eid ) $data[] = deleteRequest($eid); - break; - case 'query' : - $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit); - break; - default : - ZM\Fatal("Unrecognised task '$task'"); -} // end switch task +?> + +
+ +
+ + + + + + + + + + + +
-ajaxResponse($data); - -// -// FUNCTION DEFINITIONS -// - -function archiveRequest($task, $eid) { - $archiveVal = ($task == 'archive') ? 1 : 0; - dbQuery( - 'UPDATE Events SET Archived = ? WHERE Id = ?', - array($archiveVal, $eid) - ); -} - -function deleteRequest($eid) { - $message = array(); - $event = new ZM\Event($eid); - if ( !$event->Id() ) { - $message[] = array($eid=>'Event not found.'); - } else if ( $event->Archived() ) { - $message[] = array($eid=>'Event is archived, cannot delete it.'); - } else { - $event->delete(); - } - - return $message; -} - -function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { - // Put server pagination code here - // The table we want our data from - $table = 'Events'; - - // The names of the dB columns in the log table we are interested in - $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace'); - - // The names of columns shown in the event view that are NOT dB columns in the database - $col_alt = array('Monitor', 'Storage'); - - if ( !in_array($sort, array_merge($columns, $col_alt)) ) { - ZM\Fatal('Invalid sort field: ' . $sort); - } - - $col_str = implode(', ', $columns); - $data = array(); - $query = array(); - $query['values'] = array(); - $likes = array(); - $where = ''; - // 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) ) { - - foreach ( $advsearch as $col=>$text ) { - if ( !in_array($col, array_merge($columns, $col_alt)) ) { - ZM\Error("'$col' is not a sortable column name"); - continue; - } - $text = '%' .$text. '%'; - array_push($likes, $col.' LIKE ?'); - array_push($query['values'], $text); + +
+ + + + + + + + + + + + + + + + + + + + 1 ) { +?> + + + + + + + + + +test_post_sql_conditions($event) ) { + $event->remove_from_cache(); + continue; + } + $events[] = $event; + if ( $limit and (count($events) >= $limit) ) { + break; + } + ZM\Debug("Have " . count($events) . " events, limit $limit"); } + foreach ( $events as $event ) { - $storage_areas = ZM\Storage::find(); - $StorageById = array(); - foreach ( $storage_areas as $S ) { - $StorageById[$S->Id()] = $S; + $scale = max(reScale(SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE); +?> + Archived() ? ' class="archived"' : '' ?>> + + + + + + + + + + + + + + + + + + + 1 ) { +?> + + +Id()] = $S; + if ( ZM_WEB_EVENT_DISK_SPACE ) { + $disk_space_total += $event->DiskSpace(); +?> + +'; + $imgSrc = $event->getThumbnailSrc(array(),'&'); + $streamSrc = $event->getStreamSrc(array( + 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); - $rows = array(); - foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { - $event = new ZM\Event($row['Id']); - $scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width()); - $imgSrc = $event->getThumbnailSrc(array(),'&'); - $streamSrc = $event->getStreamSrc(array( - 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); - - // Modify the row data as needed - $row['imgHtml'] = '' .validHtmlStr('Event ' .$event->Id()). ''; - $row['Name'] = validHtmlStr($row['Name']); - $row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No'); - $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); - $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; - $row['Cause'] = validHtmlStr($row['Cause']); - $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); - $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); - $row['Length'] = gmdate('H:i:s', $row['Length'] ); - $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; - $row['Notes'] = htmlspecialchars($row['Notes']); - $row['DiskSpace'] = human_filesize($row['DiskSpace']); - $rows[] = $row; - } - $data['rows'] = $rows; - $data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG); - - return $data; + $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; + echo ''.$imgHtml.''; + echo ''; + } // end if ZM_WEB_LIST_THUMBS +?> + + + + + + + +1 ) { +?> + + + + + + + + + + + +
+
+ From 235dd2a2fb89490021296c5e3ad0fc1c3da7ca15 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 22 Oct 2020 15:06:06 -0500 Subject: [PATCH 028/169] don't use wildcards in event view advanced search fields --- web/ajax/events.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index c8e033fc9..d05da50cb 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -140,7 +140,8 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { ZM\Error("'$col' is not a sortable column name"); continue; } - $text = '%' .$text. '%'; + //Don't use wildcards. Let the user specify them if needed. + //$text = '%' .$text. '%'; array_push($likes, $col.' LIKE ?'); array_push($query['values'], $text); } From 5d7e3b05103ee65bcc964db84ee1a82f6381e419 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Oct 2020 11:12:57 -0400 Subject: [PATCH 029/169] handle no responseText in jqxhr --- web/skins/classic/js/skin.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index b33d1bb7d..aec9ee1d5 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -752,8 +752,13 @@ function stateStuff(action, runState, newState) { } function logAjaxFail(jqxhr, textStatus, error) { - var responseText = jqxhr.responseText.replace(/(<([^>]+)>)/gi, '').trim(); // strip any html or whitespace from the response console.log("Request Failed: " + textStatus + ", " + error); + if ( ! jqxhr.responseText ) { + console.log("Ajax request failed. No responseText. jqxhr follows:"); + console.log(jqxhr); + return; + } + var responseText = jqxhr.responseText.replace(/(<([^>]+)>)/gi, '').trim(); // strip any html or whitespace from the response if ( responseText ) console.log("Response Text: " + responseText); } From d425d1006e91b95660e9456276f3076c6da2cbaf Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 23 Oct 2020 10:21:32 -0500 Subject: [PATCH 030/169] push newevents.php to master --- web/ajax/events.php | 17 ++-- web/skins/classic/views/js/events.js | 2 +- web/skins/classic/views/newevents.php | 108 ++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 web/skins/classic/views/newevents.php diff --git a/web/ajax/events.php b/web/ajax/events.php index d05da50cb..75c90a311 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -114,7 +114,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { // The table we want our data from $table = 'Events'; - // The names of the dB columns in the log table we are interested in + // The names of the dB columns in the events table we are interested in $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace'); // The names of columns shown in the event view that are NOT dB columns in the database @@ -124,6 +124,14 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { ZM\Fatal('Invalid sort field: ' . $sort); } + $col_str = ''; + foreach ( $columns as $key => $col ) { + if ( $col == 'Name' ) { + $columns[$key] = 'Monitors.'.$col; + } else { + $columns[$key] = $table.'.'.$col; + } + } $col_str = implode(', ', $columns); $data = array(); $query = array(); @@ -140,8 +148,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { ZM\Error("'$col' is not a sortable column name"); continue; } - //Don't use wildcards. Let the user specify them if needed. - //$text = '%' .$text. '%'; + $text = '%' .$text. '%'; array_push($likes, $col.' LIKE ?'); array_push($query['values'], $text); } @@ -159,7 +166,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $where = ' WHERE (' .implode(' OR ', $likes). ')'; } - $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; + $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` INNER JOIN Monitors ON Events.MonitorId = Monitors.Name' .$where. ' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); ZM\Warning('Calling the following sql query: ' .$query['sql']); @@ -196,7 +203,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $row['Name'] = validHtmlStr($row['Name']); $row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No'); $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); - $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; + //$row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; $row['Cause'] = validHtmlStr($row['Cause']); $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 29c77ceb7..2743a9743 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -54,7 +54,7 @@ function processRows(rows) { row.Id = '' + eid + ''; row.Name = '' + row.Name + '' + '
' + archived + emailed + '
'; - if ( canEditMonitors ) row.Monitor = '' + row.Monitor + ''; + if ( canEditMonitors ) row.Name = '' + row.Name + ''; if ( canEditEvents ) row.Cause = '' + row.Cause + ''; if ( row.Notes.indexOf('detected:') >= 0 ) { row.Cause = row.Cause + '
' + row.Notes + '
'; diff --git a/web/skins/classic/views/newevents.php b/web/skins/classic/views/newevents.php new file mode 100644 index 000000000..133e12b8e --- /dev/null +++ b/web/skins/classic/views/newevents.php @@ -0,0 +1,108 @@ + + +
+ +
+ + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ From 8a3e0e108c786d4049d39261b426b9044b70b3e5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Oct 2020 14:02:27 -0400 Subject: [PATCH 031/169] Put back filter query code --- web/skins/classic/views/newevents.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/web/skins/classic/views/newevents.php b/web/skins/classic/views/newevents.php index 133e12b8e..73f9e4a4d 100644 --- a/web/skins/classic/views/newevents.php +++ b/web/skins/classic/views/newevents.php @@ -23,6 +23,26 @@ if ( !canView('Events') || (!empty($_REQUEST['execute']) && !canEdit('Events')) return; } +require_once('includes/Event.php'); +require_once('includes/Filter.php'); + +$eventsSql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultScale FROM Monitors AS M INNER JOIN Events AS E on (M.Id = E.MonitorId) WHERE'; +if ( $user['MonitorIds'] ) { + $user_monitor_ids = ' M.Id in ('.$user['MonitorIds'].')'; + $eventsSql .= $user_monitor_ids; +} else { + $eventsSql .= ' 1'; +} + +$filter = isset($_REQUEST['filter_id']) ? new ZM\Filter($_REQUEST['filter_id']) : new ZM\Filter(); +if ( isset($_REQUEST['filter'])) { + $filter->set($_REQUEST['filter']); +} + +parseSort(); + +$filterQuery = $filter->querystring(); + xhtmlHeaders(__FILE__, translate('Events')); getBodyTopHTML(); From da080d44c1bcb23c241f185047ae35aad70b1027 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Oct 2020 16:44:50 -0400 Subject: [PATCH 032/169] rename filter from bootstrap-table to advsearch so as not to conflict with our existing filter --- web/ajax/events.php | 2 +- web/skins/classic/views/js/events.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 75c90a311..ba3dad185 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -31,7 +31,7 @@ $search = isset($_REQUEST['search']) ? $_REQUEST['search'] : ''; // Advanced search contains an array of "column name" => "search text" pairs // Bootstrap table sends json_ecoded array, which we must decode -$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); +$advsearch = isset($_REQUEST['advsearch']) ? json_decode($_REQUEST['advsearch'], JSON_OBJECT_AS_ARRAY) : array(); // Sort specifies the name of the column to sort on $sort = 'StartTime'; diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 2743a9743..62f53a1d8 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -35,7 +35,8 @@ var params = // Called by bootstrap-table to retrieve zm event data function ajaxRequest(params) { - $j.getJSON(thisUrl + '?view=request&request=events&task=query', params.data) + console.log(params); + $j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data) .done(function(data) { var rows = processRows(data.rows); // rearrange the result into what bootstrap-table expects From 2ebd686d19310a319d15c6b8cc1eae19d9819b76 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Oct 2020 17:55:43 -0400 Subject: [PATCH 033/169] Use a ZM\Filter for initial filtering. SELECT E.*,M.* to match how we do it in Filters and older event code. pass the row into new Event() so that it doesn't go back to the DB to get the Event property data. --- web/ajax/events.php | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index ba3dad185..e420e2460 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -26,6 +26,11 @@ if ( $message ) { return; } +$filter = isset($_REQUEST['filter']) ? ZM\Filter::parse($_REQUEST['filter']) : new ZM\Filter(); +if ( $user['MonitorIds'] ) { + $filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds'])); +} + // Search contains a user entered string to search on $search = isset($_REQUEST['search']) ? $_REQUEST['search'] : ''; @@ -75,7 +80,7 @@ switch ( $task ) { foreach ( $eids as $eid ) $data[] = deleteRequest($eid); break; case 'query' : - $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit); + $data = queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit); break; default : ZM\Fatal("Unrecognised task '$task'"); @@ -109,7 +114,7 @@ function deleteRequest($eid) { return $message; } -function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { +function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $limit) { // Put server pagination code here // The table we want our data from $table = 'Events'; @@ -127,9 +132,9 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $col_str = ''; foreach ( $columns as $key => $col ) { if ( $col == 'Name' ) { - $columns[$key] = 'Monitors.'.$col; + $columns[$key] = 'M.'.$col; } else { - $columns[$key] = $table.'.'.$col; + $columns[$key] = 'E.'.$col; } } $col_str = implode(', ', $columns); @@ -137,7 +142,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $query = array(); $query['values'] = array(); $likes = array(); - $where = ''; + $where = ($filter->sql()?'('.$filter->sql().')' : ''); // 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 @@ -153,7 +158,7 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { array_push($query['values'], $text); } $wherevalues = $query['values']; - $where = ' WHERE (' .implode(' OR ', $likes). ')'; + $where = ' AND (' .implode(' OR ', $likes). ')'; } else if ( $search != '' ) { @@ -163,17 +168,20 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { array_push($query['values'], $search); } $wherevalues = $query['values']; - $where = ' WHERE (' .implode(' OR ', $likes). ')'; - } + $where = ' AND (' .implode(' OR ', $likes). ')'; + } + if ( $where ) + $where = ' WHERE '.$where; - $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` INNER JOIN Monitors ON Events.MonitorId = Monitors.Name' .$where. ' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; + $col_str = 'E.*'; + $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); ZM\Warning('Calling the following sql query: ' .$query['sql']); - $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); + $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table . ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); if ( $search != '' || count($advsearch) ) { - $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues); + $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table . ' AS E'.$where , 'Total', $wherevalues); } else { $data['total'] = $data['totalNotFiltered']; } @@ -192,7 +200,8 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $rows = array(); foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { - $event = new ZM\Event($row['Id']); + ZM\Debug("row".print_r($row,true)); + $event = new ZM\Event($row); $scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width()); $imgSrc = $event->getThumbnailSrc(array(),'&'); $streamSrc = $event->getStreamSrc(array( From b6004012e993e2fd16145ee7cfd065fbe88081d4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Oct 2020 17:56:05 -0400 Subject: [PATCH 034/169] implement passing the object name to use when constructing the querystring --- web/includes/Filter.php | 8 ++++---- web/includes/FilterTerm.php | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/web/includes/Filter.php b/web/includes/Filter.php index 510717544..b6c163f91 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -52,14 +52,14 @@ class Filter extends ZM_Object { return $this->_sql; } - public function querystring($separator='&') { - if ( (! isset($this->_querystring)) or ( $separator != '&' ) ) { + public function querystring($objectname='filter', $separator='&') { + if ( (! isset($this->_querystring)) or ( $separator != '&' ) or ($objectname != 'filter') ) { $this->_querystring = ''; foreach ( $this->FilterTerms() as $term ) { - $this->_querystring .= $term->querystring($separator); + $this->_querystring .= $term->querystring($objectname, $separator); } # end foreach term if ( $this->Id() ) { - $this->_querystring .= $separator.'filter[Id]='.$this->Id(); + $this->_querystring .= $separator.$objectname.'[Id]='.$this->Id(); } } return $this->_querystring; diff --git a/web/includes/FilterTerm.php b/web/includes/FilterTerm.php index fca0c9e20..4b2b1b78e 100644 --- a/web/includes/FilterTerm.php +++ b/web/includes/FilterTerm.php @@ -292,19 +292,19 @@ class FilterTerm { return $sql; } # end public function sql - public function querystring($querySep='&') { + public function querystring($objectname='filter', $querySep='&') { # We don't validate the term parameters here $query = ''; if ( $this->cnj ) - $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][cnj]').'='.$this->cnj; + $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cnj]').'='.$this->cnj; if ( $this->obr ) - $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][obr]').'='.$this->obr; + $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][obr]').'='.$this->obr; - $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][attr]').'='.urlencode($this->attr); - $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][op]').'='.urlencode($this->op); - $query .= $querySep.urlencode('filter[Query][terms]['.$this->index.'][val]').'='.urlencode($this->val); + $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('filter[Query][terms]['.$this->index.'][cbr]').'='.$this->cbr; + $query .= $querySep.urlencode($objectname.'[Query][terms]['.$this->index.'][cbr]').'='.$this->cbr; return $query; } # end public function querystring From 2178da387d709cf563ff947cefb41b439229ec10 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Oct 2020 17:56:38 -0400 Subject: [PATCH 035/169] pass desired object name into querystring() --- web/includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 40306e0ec..725c9baac 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -1080,7 +1080,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') { $Filter = ZM\Filter::parse($filter, $querySep); $filter['sql'] = $Filter->sql(); - $filter['querystring'] = $Filter->querystring($querySep); + $filter['querystring'] = $Filter->querystring('filter', $querySep); $filter['hidden_fields'] = $Filter->hidden_fields(); $filter['pre_sql_conditions'] = $Filter->pre_sql_conditions(); $filter['post_sql_conditions'] = $Filter->post_sql_conditions(); From 760e20bc0f7504e5539b0c07963d74ea6dce12d9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 24 Oct 2020 08:50:59 -0400 Subject: [PATCH 036/169] Populate Monitor name and use event class DiskSpace to get DiskSpace when it hasn't been populated in the db yet --- web/ajax/events.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index e420e2460..d224b8742 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -212,14 +212,14 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $row['Name'] = validHtmlStr($row['Name']); $row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No'); $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); - //$row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; + $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; $row['Cause'] = validHtmlStr($row['Cause']); $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['Length'] = gmdate('H:i:s', $row['Length'] ); $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; $row['Notes'] = htmlspecialchars($row['Notes']); - $row['DiskSpace'] = human_filesize($row['DiskSpace']); + $row['DiskSpace'] = human_filesize($event->DiskSpace()); $rows[] = $row; } $data['rows'] = $rows; From efaf95bedaed2e395002a05c9044cd4fb62370c1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 24 Oct 2020 08:51:26 -0400 Subject: [PATCH 037/169] dirty hack to rename data.filter to data.advsearch --- web/skins/classic/views/js/events.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 62f53a1d8..90bce5f5f 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -35,7 +35,10 @@ var params = // Called by bootstrap-table to retrieve zm event data function ajaxRequest(params) { - console.log(params); + if ( params.data.filter ) { + params.data.advsearch = params.data.filter; + delete params.data.filter; + } $j.getJSON(thisUrl + '?view=request&request=events&task=query'+filterQuery, params.data) .done(function(data) { var rows = processRows(data.rows); From 90c5f63d6d11f5edfb72b16cae4a5df188cccc86 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 24 Oct 2020 09:05:39 -0400 Subject: [PATCH 038/169] Fix session.gc SQL issue. Don't need a * when deleting --- web/includes/session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/session.php b/web/includes/session.php index 34ce8b13c..0190f9897 100644 --- a/web/includes/session.php +++ b/web/includes/session.php @@ -147,7 +147,7 @@ class Session { $now = time(); $old = $now - $max; ZM\Debug('doing session gc ' . $now . '-' . $max. '='.$old); - $sth = $this->db->prepare('DELETE * FROM Sessions WHERE access < :old'); + $sth = $this->db->prepare('DELETE FROM Sessions WHERE access < :old'); $sth->bindParam(':old', $old, PDO::PARAM_INT); return $sth->execute() ? true : false; } From a2dc4b5f08aaa2fc8237540e532eccdc5976dbe6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 24 Oct 2020 09:45:38 -0400 Subject: [PATCH 039/169] handle params.daa not existing --- web/skins/classic/views/js/events.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 90bce5f5f..442eca616 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -35,7 +35,7 @@ var params = // Called by bootstrap-table to retrieve zm event data function ajaxRequest(params) { - if ( params.data.filter ) { + if ( params.data && params.data.filter ) { params.data.advsearch = params.data.filter; delete params.data.filter; } From f87be2d2895b7c3f0f77f9a42ff4b56c87155bbb Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Oct 2020 08:24:56 -0500 Subject: [PATCH 040/169] specify the table name when we sort in events view --- web/ajax/events.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index d224b8742..eddd62463 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -173,6 +173,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim if ( $where ) $where = ' WHERE '.$where; + $sort = $sort == "Name" ? 'M.'.$sort : 'E.'.$sort; $col_str = 'E.*'; $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); @@ -192,12 +193,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $StorageById[$S->Id()] = $S; } - $monitor_names = ZM\Monitor::find(); - $MonitorById = array(); - foreach ( $monitor_names as $S ) { - $MonitorById[$S->Id()] = $S; - } - $rows = array(); foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { ZM\Debug("row".print_r($row,true)); @@ -212,7 +207,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $row['Name'] = validHtmlStr($row['Name']); $row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No'); $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); - $row['Monitor'] = ( $row['MonitorId'] and isset($MonitorById[$row['MonitorId']]) ) ? $MonitorById[$row['MonitorId']]->Name() : ''; $row['Cause'] = validHtmlStr($row['Cause']); $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); From cb073950b93a6e39955f851e8ed9aea6afef34ab Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Oct 2020 10:28:22 -0500 Subject: [PATCH 041/169] events view server pagination WIP --- web/ajax/events.php | 11 +---------- web/skins/classic/views/js/events.js | 2 +- web/skins/classic/views/newevents.php | 2 +- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index eddd62463..f6be6e501 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -129,15 +129,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim ZM\Fatal('Invalid sort field: ' . $sort); } - $col_str = ''; - foreach ( $columns as $key => $col ) { - if ( $col == 'Name' ) { - $columns[$key] = 'M.'.$col; - } else { - $columns[$key] = 'E.'.$col; - } - } - $col_str = implode(', ', $columns); $data = array(); $query = array(); $query['values'] = array(); @@ -174,7 +165,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $where = ' WHERE '.$where; $sort = $sort == "Name" ? 'M.'.$sort : 'E.'.$sort; - $col_str = 'E.*'; + $col_str = 'E.*, M.Name AS Monitor'; $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 442eca616..b51c679a3 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -58,7 +58,7 @@ function processRows(rows) { row.Id = '' + eid + ''; row.Name = '' + row.Name + '' + '
' + archived + emailed + '
'; - if ( canEditMonitors ) row.Name = '' + row.Name + ''; + if ( canEditMonitors ) row.Monitor = '' + row.Monitor + ''; if ( canEditEvents ) row.Cause = '' + row.Cause + ''; if ( row.Notes.indexOf('detected:') >= 0 ) { row.Cause = row.Cause + '
' + row.Notes + '
'; diff --git a/web/skins/classic/views/newevents.php b/web/skins/classic/views/newevents.php index 73f9e4a4d..555f13f51 100644 --- a/web/skins/classic/views/newevents.php +++ b/web/skins/classic/views/newevents.php @@ -102,7 +102,7 @@ getBodyTopHTML(); - + From e9b71b4ce17f8c23ecfa6625d51f9b84b9eab823 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Oct 2020 10:40:29 -0500 Subject: [PATCH 042/169] events view server pagination - fix sorting name & monitor --- web/ajax/events.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index f6be6e501..eb74f543a 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -164,9 +164,10 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim if ( $where ) $where = ' WHERE '.$where; - $sort = $sort == "Name" ? 'M.'.$sort : 'E.'.$sort; + $sort = $sort == "Monitor" ? 'M.Name' : 'E.'.$sort; $col_str = 'E.*, M.Name AS Monitor'; - $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; + //$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; + $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); ZM\Warning('Calling the following sql query: ' .$query['sql']); From 8cf899efc5dbf2f74292014cf80bbdf5ccb5c631 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Oct 2020 10:58:27 -0500 Subject: [PATCH 043/169] remove commented line --- web/ajax/events.php | 1 - 1 file changed, 1 deletion(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index eb74f543a..c27817be3 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -166,7 +166,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $sort = $sort == "Monitor" ? 'M.Name' : 'E.'.$sort; $col_str = 'E.*, M.Name AS Monitor'; - //$query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); From 6d00924c9b23539e9cde6f6bfc9b532f9bea7eb7 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Oct 2020 12:11:34 -0500 Subject: [PATCH 044/169] deploy server pagination for events view --- web/skins/classic/views/events.php | 233 ++------------------------ web/skins/classic/views/js/events.js | 7 - web/skins/classic/views/newevents.php | 128 -------------- 3 files changed, 15 insertions(+), 353 deletions(-) delete mode 100644 web/skins/classic/views/newevents.php diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index a70fa8d19..555f13f51 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -42,73 +42,6 @@ if ( isset($_REQUEST['filter'])) { parseSort(); $filterQuery = $filter->querystring(); -ZM\Debug('Filter '.print_r($filter, true)); - -if ( $filter->sql() ) { - $eventsSql .= ' AND ('.$filter->sql().')'; -} else { - ZM\Warning('No filters'); - exit; -} -$eventsSql .= ' ORDER BY '.$sortColumn.' '.$sortOrder; -if ( $sortColumn != 'E.Id' ) $eventsSql .= ',E.Id '.$sortOrder; - -$page = isset($_REQUEST['page']) ? validInt($_REQUEST['page']) : 0; -$limit = isset($_REQUEST['limit']) ? validInt($_REQUEST['limit']) : $filter['limit']; - -if ( $_POST ) { - // I think this is basically so that a refresh doesn't repost - ZM\Debug('Redirecting to ' . $_SERVER['REQUEST_URI']); - header('Location: ?view=' . $view.htmlspecialchars_decode($filterQuery).htmlspecialchars_decode($sortQuery).$limitQuery.'&page='.$page); - exit(); -} - -$failed = !$filter->test_pre_sql_conditions(); -if ( $failed ) { - ZM\Debug('Pre conditions failed, not doing sql'); -} - -$results = $failed ? null : dbQuery($eventsSql); - -$nEvents = $results ? $results->rowCount() : 0; -if ( ! $results ) { - global $error_message; - $error_message = dbError($eventsSql); -} -ZM\Debug("Pre conditions succeeded sql return $nEvents events"); - -if ( !empty($limit) && ($nEvents > $limit) ) { - $nEvents = $limit; -} -$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE); -#Debug("Page $page Limit $limit #vents: $nEvents pages: $pages "); -if ( !empty($page) ) { - if ( $page < 0 ) - $page = 1; - else if ( $pages and ( $page > $pages ) ) - $page = $pages; - - $limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE); - if ( empty($limit) ) { - $limitAmount = ZM_WEB_EVENTS_PER_PAGE; - } else { - $limitLeft = $limit - $limitStart; - $limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft; - } - $eventsSql .= ' LIMIT '.$limitStart.', '.$limitAmount; -} else if ( !empty($limit) ) { - $eventsSql .= ' LIMIT 0, '.$limit; -} - -$maxShortcuts = 5; - -$focusWindow = true; - -$storage_areas = ZM\Storage::find(); -$StorageById = array(); -foreach ( $storage_areas as $S ) { - $StorageById[$S->Id()] = $S; -} xhtmlHeaders(__FILE__, translate('Events')); getBodyTopHTML(); @@ -136,6 +69,8 @@ getBodyTopHTML(); @@ -168,163 +104,24 @@ getBodyTopHTML(); - - - + + + - - - - - 1 ) { -?> - - + + + + + - - - - - - while ( $event_row = dbFetchNext($results) ) { - $event = new ZM\Event($event_row); - - if ( !$filter->test_post_sql_conditions($event) ) { - $event->remove_from_cache(); - continue; - } - $events[] = $event; - if ( $limit and (count($events) >= $limit) ) { - break; - } - ZM\Debug("Have " . count($events) . " events, limit $limit"); - } - foreach ( $events as $event ) { - - $scale = max(reScale(SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE), SCALE_BASE); -?> - Archived() ? ' class="archived"' : '' ?>> - - - - - - - - - - - - - - - - - - - 1 ) { -?> - - -DiskSpace(); -?> - -'; - $imgSrc = $event->getThumbnailSrc(array(),'&'); - $streamSrc = $event->getStreamSrc(array( - 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); - - $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; - echo ''.$imgHtml.''; - echo ''; - } // end if ZM_WEB_LIST_THUMBS -?> - - + + - - - - -1 ) { -?> - - - - - - - - - - +
diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index b51c679a3..d98d51f4f 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -321,13 +321,6 @@ function initPage() { $j('#deleteConfirm').modal('show'); }); - // Manage the eventdetail links in the events list - $j(".eDetailLink").click(function(evt) { - evt.preventDefault(); - var eid = $j(this).data('eid'); - getEventDetailModal(eid); - }); - // Update table links each time after new data is loaded table.on('post-body.bs.table', function(data) { // Manage the eventdetail links in the events list diff --git a/web/skins/classic/views/newevents.php b/web/skins/classic/views/newevents.php deleted file mode 100644 index 555f13f51..000000000 --- a/web/skins/classic/views/newevents.php +++ /dev/null @@ -1,128 +0,0 @@ -set($_REQUEST['filter']); -} - -parseSort(); - -$filterQuery = $filter->querystring(); - -xhtmlHeaders(__FILE__, translate('Events')); -getBodyTopHTML(); - -?> - -
- -
- - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- From e5563dc901d4563e76109793b4acf51a5c169b7d Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Oct 2020 16:06:37 -0500 Subject: [PATCH 045/169] remove unwanted # --- web/skins/classic/views/js/events.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index d98d51f4f..b657c50cf 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -61,7 +61,7 @@ function processRows(rows) { if ( canEditMonitors ) row.Monitor = '' + row.Monitor + ''; if ( canEditEvents ) row.Cause = '' + row.Cause + ''; if ( row.Notes.indexOf('detected:') >= 0 ) { - row.Cause = row.Cause + '
' + row.Notes + '
'; + row.Cause = row.Cause + '
' + row.Notes + '
'; } else if ( row.Notes != 'Forced Web: ' ) { row.Cause = row.Cause + '
' + row.Notes + '
'; } From 706bf085f4b4ab63d8823acad56edf6bef79bd80 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 09:58:47 -0400 Subject: [PATCH 046/169] Add pre and post sql conditions and pre-populate the return --- web/ajax/events.php | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index d224b8742..8a2d735ca 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -115,6 +115,19 @@ function deleteRequest($eid) { } function queryRequest($filter, $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) + ); + + $failed = !$filter->test_pre_sql_conditions(); + if ( $failed ) { + ZM\Debug('Pre conditions failed, not doing sql'); + return $data; + } + // Put server pagination code here // The table we want our data from $table = 'Events'; @@ -138,7 +151,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } } $col_str = implode(', ', $columns); - $data = array(); $query = array(); $query['values'] = array(); $likes = array(); @@ -177,14 +189,8 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY LENGTH(' .$sort. '), ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); - ZM\Warning('Calling the following sql query: ' .$query['sql']); + ZM\Debug('Calling the following sql query: ' .$query['sql']); - $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table . ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); - if ( $search != '' || count($advsearch) ) { - $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table . ' AS E'.$where , 'Total', $wherevalues); - } else { - $data['total'] = $data['totalNotFiltered']; - } $storage_areas = ZM\Storage::find(); $StorageById = array(); @@ -202,6 +208,10 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { ZM\Debug("row".print_r($row,true)); $event = new ZM\Event($row); + if ( !$filter->test_post_sql_conditions($event) ) { + $event->remove_from_cache(); + continue; + } $scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width()); $imgSrc = $event->getThumbnailSrc(array(),'&'); $streamSrc = $event->getStreamSrc(array( @@ -223,8 +233,9 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $rows[] = $row; } $data['rows'] = $rows; - $data['updated'] = preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG); + $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); + $data['total'] = count($rows); return $data; } ?> From 4c791b390f73ea5a538569c88c5d46d2a28654b1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 09:59:15 -0400 Subject: [PATCH 047/169] fix warning due to undefined vars being used --- web/ajax/log.php | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index bde07ed65..22897fd04 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -66,7 +66,7 @@ if ( isset($_REQUEST['limit']) ) { switch ( $task ) { case 'create' : - createRequest($task, $eid); + createRequest(); break; case 'query' : $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit); @@ -82,27 +82,27 @@ ajaxResponse($data); // function createRequest() { - if ( !empty($_POST['level']) && !empty($_POST['message']) ) { - ZM\logInit(array('id'=>'web_js')); + if ( !empty($_POST['level']) && !empty($_POST['message']) ) { + ZM\logInit(array('id'=>'web_js')); - $string = $_POST['message']; + $string = $_POST['message']; - $file = !empty($_POST['file']) ? preg_replace('/\w+:\/\/[\w.:]+\//', '', $_POST['file']) : ''; - if ( !empty($_POST['line']) ) { - $line = validInt($_POST['line']); - } else { - $line = NULL; - } - - $levels = array_flip(ZM\Logger::$codes); - if ( !isset($levels[$_POST['level']]) ) { - ZM\Panic('Unexpected logger level '.$_POST['level']); - } - $level = $levels[$_POST['level']]; - ZM\Logger::fetch()->logPrint($level, $string, $file, $line); + $file = !empty($_POST['file']) ? preg_replace('/\w+:\/\/[\w.:]+\//', '', $_POST['file']) : ''; + if ( !empty($_POST['line']) ) { + $line = validInt($_POST['line']); } else { - ZM\Error('Invalid log create: '.print_r($_POST, true)); + $line = NULL; } + + $levels = array_flip(ZM\Logger::$codes); + if ( !isset($levels[$_POST['level']]) ) { + ZM\Panic('Unexpected logger level '.$_POST['level']); + } + $level = $levels[$_POST['level']]; + ZM\Logger::fetch()->logPrint($level, $string, $file, $line); + } else { + ZM\Error('Invalid log create: '.print_r($_POST, true)); + } } function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { From 27b39a0258d58480c2ec6c6371bd75aade341710 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 26 Oct 2020 09:19:08 -0500 Subject: [PATCH 048/169] comment out warning used for debug --- web/ajax/events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index c27817be3..ff2c5b426 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -169,7 +169,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); - ZM\Warning('Calling the following sql query: ' .$query['sql']); + //ZM\Warning('Calling the following sql query: ' .$query['sql']); $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table . ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); if ( $search != '' || count($advsearch) ) { From 97573122bc090e0a9f88c8b0d54a73d9337739b6 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 26 Oct 2020 09:33:11 -0500 Subject: [PATCH 049/169] fix EndTime --- web/ajax/events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index ff2c5b426..c13be849d 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -200,7 +200,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); $row['Cause'] = validHtmlStr($row['Cause']); $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); - $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); + $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndTime'])); $row['Length'] = gmdate('H:i:s', $row['Length'] ); $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; $row['Notes'] = htmlspecialchars($row['Notes']); From da87b5b475145bbda71d57f8ae1717e676dfd514 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 13:06:05 -0400 Subject: [PATCH 050/169] Make invalid sort field non-fatal. Fix column specification in search and advscearch and fix resulting sql due to = instead of .= --- web/ajax/events.php | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 51df45035..4046c69f1 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -139,7 +139,8 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $col_alt = array('Monitor', 'Storage'); if ( !in_array($sort, array_merge($columns, $col_alt)) ) { - ZM\Fatal('Invalid sort field: ' . $sort); + ZM\Error('Invalid sort field: ' . $sort); + $sort = 'Id'; } $data = array(); @@ -153,26 +154,31 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim if ( count($advsearch) ) { foreach ( $advsearch as $col=>$text ) { - if ( !in_array($col, array_merge($columns, $col_alt)) ) { + if ( in_array($col, $columns) ) { + $text = '%' .$text. '%'; + array_push($likes, 'E.'.$col.' LIKE ?'); + array_push($query['values'], $text); + } else if ( in_array($col, $col_alt) ) { + $text = '%' .$text. '%'; + array_push($likes, 'M.'.$col.' LIKE ?'); + array_push($query['values'], $text); + } else { ZM\Error("'$col' is not a sortable column name"); continue; } - $text = '%' .$text. '%'; - array_push($likes, $col.' LIKE ?'); - array_push($query['values'], $text); - } + } # end foreach col in advsearch $wherevalues = $query['values']; - $where = ' AND (' .implode(' OR ', $likes). ')'; + $where .= ($where != '') ? ' AND (' .implode(' OR ', $likes). ')' : implode(' OR ', $likes); } else if ( $search != '' ) { $search = '%' .$search. '%'; foreach ( $columns as $col ) { - array_push($likes, $col.' LIKE ?'); + array_push($likes, 'E.'.$col.' LIKE ?'); array_push($query['values'], $search); } $wherevalues = $query['values']; - $where = ' AND (' .implode(' OR ', $likes). ')'; + $where .= ( $where != '') ? ' AND (' .implode(' OR ', $likes). ')' : implode(' OR ', $likes); } if ( $where ) $where = ' WHERE '.$where; From 59cf5c33c24991c3aeee39b65df9a549228c45a6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 13:06:22 -0400 Subject: [PATCH 051/169] reset search on events load --- web/skins/classic/views/js/events.js | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index b657c50cf..ed591e510 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -336,6 +336,7 @@ function initPage() { table.find("tr td:nth-child(" + (thumb_ndx+1) + ")").addClass('colThumbnail zoom'); }); + table.bootstrapTable('resetSearch'); // The table is initially given a hidden style, so now that we are done rendering, show it table.show(); } From 1f64a263eb3da2d007bbf6b72c84d4eba1364857 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 13:06:41 -0400 Subject: [PATCH 052/169] give better log when jqxhr is empty --- web/skins/classic/js/skin.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index aec9ee1d5..f6cbb328a 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -351,6 +351,11 @@ if ( currentView != 'none' && currentView != 'login' ) { .done(setNavBar) .fail(function(jqxhr, textStatus, error) { console.log("Request Failed: " + textStatus + ", " + error); + if ( ! jqxhr.responseText ) { + console.log("No responseText in jqxhr"); + console.log(jqxhr); + return; + } console.log("Response Text: " + jqxhr.responseText.replace(/(<([^>]+)>)/gi, '')); if ( textStatus != "timeout" ) { // The idea is that this should only fail due to auth, so reload the page From fad4339713fe5ae8709f5a78d500429a42828f2a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 26 Oct 2020 12:12:50 -0500 Subject: [PATCH 053/169] no need for full page reload with server pagination --- web/skins/classic/views/js/events.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index ed591e510..f0bd0b3ac 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -135,7 +135,7 @@ function manageDelConfirmModalBtns() { $j.getJSON(thisUrl + '?request=events&task=delete&eids[]='+selections.join('&eids[]=')) .done( function(data) { $j('#eventTable').bootstrapTable('refresh'); - window.location.reload(true); + $j('#deleteConfirm').modal('hide'); }) .fail(logAjaxFail); }); @@ -238,7 +238,6 @@ function initPage() { $j.getJSON(thisUrl + '?request=events&task=archive&eids[]='+selections.join('&eids[]=')) .done( function(data) { $j('#eventTable').bootstrapTable('refresh'); - window.location.reload(true); }) .fail(logAjaxFail); }); @@ -257,11 +256,8 @@ function initPage() { $j.getJSON(thisUrl + '?request=events&task=unarchive&eids[]='+selections.join('&eids[]=')) .done( function(data) { $j('#eventTable').bootstrapTable('refresh'); - window.location.reload(true); }) .fail(logAjaxFail); - - //window.location.reload(true); }); // Manage the EDIT button From 7b106e2522eaa0289391d17e5de45de85fa6ce78 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 26 Oct 2020 12:20:26 -0500 Subject: [PATCH 054/169] don't use wildcards in advanced search --- web/ajax/events.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 32e8f7ce9..850628109 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -155,11 +155,11 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim foreach ( $advsearch as $col=>$text ) { if ( in_array($col, $columns) ) { - $text = '%' .$text. '%'; + //$text = '%' .$text. '%'; array_push($likes, 'E.'.$col.' LIKE ?'); array_push($query['values'], $text); } else if ( in_array($col, $col_alt) ) { - $text = '%' .$text. '%'; + //$text = '%' .$text. '%'; array_push($likes, 'M.'.$col.' LIKE ?'); array_push($query['values'], $text); } else { From 1fde123ebc9f03de0bf31df5728435716f15a0e0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:47:03 -0400 Subject: [PATCH 055/169] add LockRows to Filters --- db/zm_create.sql.in | 1 + 1 file changed, 1 insertion(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 71d07ad07..a8b83826f 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -303,6 +303,7 @@ CREATE TABLE `Filters` ( `UpdateDiskSpace` tinyint(3) unsigned NOT NULL default '0', `Background` tinyint(1) unsigned NOT NULL default '0', `Concurrent` tinyint(1) unsigned NOT NULL default '0', + `LockRows` tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (`Id`), KEY `Name` (`Name`) ) ENGINE=@ZM_MYSQL_ENGINE@; From a2596505e9ccd604b280af01c346bf89c6761bf7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:47:17 -0400 Subject: [PATCH 056/169] add LockRows to Filters --- web/includes/Filter.php | 1 + web/skins/classic/views/filter.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/web/includes/Filter.php b/web/includes/Filter.php index b6c163f91..bd22f3b89 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -29,6 +29,7 @@ class Filter extends ZM_Object { 'Background' => 0, 'Concurrent' => 0, 'Query_json' => '', + 'LockRows' => 0, ); protected $_querystring; diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 96e0b9728..d53fff02a 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -485,6 +485,10 @@ if ( ZM_OPT_MESSAGE ) { Concurrent() ) { ?> checked="checked" data-on-click-this="updateButtons"/>

+

+ + LockRows() ) { ?> checked="checked" data-on-click-this="updateButtons"/> +


From 7a65a6464458a307861139417324faf65518a7c6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:47:40 -0400 Subject: [PATCH 057/169] add LockRows to Filters --- scripts/ZoneMinder/lib/ZoneMinder/Filter.pm | 3 +++ scripts/zmfilter.pl.in | 2 ++ 2 files changed, 5 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm index 9bb13132c..85c09b141 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm @@ -77,6 +77,7 @@ UpdateDiskSpace UserId Background Concurrent +LockRows ); sub Execute { @@ -103,6 +104,8 @@ sub Execute { $sql =~ s/zmSystemLoad/$load/g; } + $sql .= ' FOR UPDATE' if $$self{LockRows}; + Debug("Filter::Execute SQL ($sql)"); my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql) or Fatal("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr()); diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 9a93c8953..5540e6944 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -277,6 +277,7 @@ FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) { sub checkFilter { my $filter = shift; + my $in_transaction = ZoneMinder::Database::start_transaction($dbh) if $$filter{LockRows}; my @Events = $filter->Execute(); Debug( join(' ', @@ -396,6 +397,7 @@ sub checkFilter { $ZoneMinder::Database::dbh->commit(); } # end if UpdateDiskSpace } # end foreach event + ZoneMinder::Database::end_transaction($dbh, $in_transaction) if $$filter{LockRows}; } # end sub checkFilter sub generateVideo { From ffc5249a665edaa1d5bacbe9081d0f1593574a95 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:47:55 -0400 Subject: [PATCH 058/169] add LockRows to Filters --- web/lang/en_gb.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index b80121bed..0877f7399 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -371,6 +371,7 @@ $SLANG = array( 'FilterUpdateDiskSpace' => 'Update used disk space', 'FilterDeleteEvents' => 'Delete all matches', 'FilterCopyEvents' => 'Copy all matches', + 'FilterLockRows' => 'Lock Rows', 'FilterMoveEvents' => 'Move all matches', 'FilterEmailEvents' => 'Email details of all matches', 'FilterEmailTo' => 'Email To', From cd9b16a467da7c3ccb6fe2a1453a6d67a51080c9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:48:16 -0400 Subject: [PATCH 059/169] add LockRows to Filters --- db/zm_update-1.35.11.sql | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 db/zm_update-1.35.11.sql diff --git a/db/zm_update-1.35.11.sql b/db/zm_update-1.35.11.sql new file mode 100644 index 000000000..b8c54f713 --- /dev/null +++ b/db/zm_update-1.35.11.sql @@ -0,0 +1,18 @@ +-- +-- Update Filters table to have a LockRows Column +-- + +SELECT 'Checking for LockRows in Filters'; +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Filters' + AND table_schema = DATABASE() + AND column_name = 'LockRows' + ) > 0, +"SELECT 'Column LockRows already exists in Filters'", +"ALTER TABLE Filters ADD COLUMN `LockRows` tinyint(1) unsigned NOT NULL default '0' AFTER `Concurrent`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; From f3f0a6baff2de703928a23ef2362d5fd4b053cfa Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:48:43 -0400 Subject: [PATCH 060/169] remove debug --- src/zm_ffmpeg_camera.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index e04f5e8ca..7d990bcd2 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -664,7 +664,6 @@ int FfmpegCamera::OpenFfmpeg() { } // int FfmpegCamera::OpenFfmpeg() int FfmpegCamera::Close() { - Debug(2, "CloseFfmpeg called."); mCanCapture = false; From a5bb2365b54d09fcc983e72a77a28582a961ab8f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:49:03 -0400 Subject: [PATCH 061/169] update auth_relay when we update auth_hash --- web/skins/classic/js/skin.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index f6cbb328a..85449927c 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -372,10 +372,14 @@ if ( currentView != 'none' && currentView != 'login' ) { } if ( data.auth ) { if ( data.auth != auth_hash ) { + console.log("Update auth_hash to "+data.auth); // Update authentication token. auth_hash = data.auth; } } + if ( data.auth_relay ) { + auth_relay = data.auth_relay; + } // iterate through all the keys then update each element id with the same name for (var key of Object.keys(data)) { if ( key == "auth" ) continue; From 1690bcbd381a4f461bbbf5ac72c091212037c116 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:49:14 -0400 Subject: [PATCH 062/169] update auth_relay when we update auth_hash --- web/ajax/status.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/ajax/status.php b/web/ajax/status.php index 0bafe16e4..190d239ad 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -6,6 +6,7 @@ if ( $_REQUEST['entity'] == 'navBar' ) { $auth_hash = generateAuthHash(ZM_AUTH_HASH_IPS); if ( isset($_REQUEST['auth']) and ($_REQUEST['auth'] != $auth_hash) ) { $data['auth'] = $auth_hash; + $data['auth_relay'] = get_auth_relay(); } } // Each widget on the navbar has its own function From c67b3c5a1f1189e41f2cf617481a7874785378b8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Oct 2020 18:49:41 -0400 Subject: [PATCH 063/169] fix button disabled status. We now have checkboxes that aren't actions so we need to be more explicit --- web/skins/classic/views/js/filter.js | 53 +++++++++++++--------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js index fd7ee94ca..707fb06e1 100644 --- a/web/skins/classic/views/js/filter.js +++ b/web/skins/classic/views/js/filter.js @@ -74,35 +74,32 @@ function validateForm(form) { function updateButtons(element) { var form = element.form; - if ( element.type == 'checkbox' && element.checked ) { - form.elements['executeButton'].disabled = false; - } else { - var canExecute = false; - if ( form.elements['filter[AutoArchive]'] && form.elements['filter[AutoArchive]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoUnarchive]'] && form.elements['filter[AutoUnarchive]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoCopy]'] && form.elements['filter[AutoCopy]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoMove]'] && form.elements['filter[AutoMove]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoVideo]'] && form.elements['filter[AutoVideo]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoUpload]'] && form.elements['filter[AutoUpload]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoEmail]'] && form.elements['filter[AutoEmail]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoMessage]'] && form.elements['filter[AutoMessage]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[AutoExecute]'].checked && form.elements['filter[AutoExecuteCmd]'].value != '' ) { - canExecute = true; - } else if ( form.elements['filter[AutoDelete]'].checked ) { - canExecute = true; - } else if ( form.elements['filter[UpdateDiskSpace]'].checked ) { - canExecute = true; - } - form.elements['executeButton'].disabled = !canExecute; + + var canExecute = false; + if ( form.elements['filter[AutoArchive]'] && form.elements['filter[AutoArchive]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoUnarchive]'] && form.elements['filter[AutoUnarchive]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoCopy]'] && form.elements['filter[AutoCopy]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoMove]'] && form.elements['filter[AutoMove]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoVideo]'] && form.elements['filter[AutoVideo]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoUpload]'] && form.elements['filter[AutoUpload]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoEmail]'] && form.elements['filter[AutoEmail]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoMessage]'] && form.elements['filter[AutoMessage]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[AutoExecute]'].checked && form.elements['filter[AutoExecuteCmd]'].value != '' ) { + canExecute = true; + } else if ( form.elements['filter[AutoDelete]'].checked ) { + canExecute = true; + } else if ( form.elements['filter[UpdateDiskSpace]'].checked ) { + canExecute = true; } + form.elements['executeButton'].disabled = !canExecute; if ( form.elements['filter[Name]'].value ) { form.elements['Save'].disabled = false; form.elements['SaveAs'].disabled = false; From 3825af8243e997eaec725aa2a967ba422a3bf652 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 09:19:54 -0400 Subject: [PATCH 064/169] Add FOREIGN KEYS for EventId in Frames, Stats. MonitorId, ZoneId in Stats. MonitorId in Zones. --- db/zm_create.sql.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 71d07ad07..940ba2a82 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -315,6 +315,7 @@ DROP TABLE IF EXISTS `Frames`; CREATE TABLE `Frames` ( `Id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `EventId` BIGINT UNSIGNED NOT NULL default '0', + FOREIGN KEY (`EventId`) REFERENCES `Events` (`Id`) ON DELETE CASCADE, `FrameId` int(10) unsigned NOT NULL default '0', `Type` enum('Normal','Bulk','Alarm') NOT NULL default 'Normal', `TimeStamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, @@ -608,8 +609,11 @@ DROP TABLE IF EXISTS `Stats`; CREATE TABLE `Stats` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, `MonitorId` int(10) unsigned NOT NULL default '0', + FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE, `ZoneId` int(10) unsigned NOT NULL default '0', + FOREIGN KEY (`ZoneId`) REFERENCES `Zones` (`Id`) ON DELETE CASCADE, `EventId` BIGINT UNSIGNED NOT NULL, + FOREIGN KEY (`EventId`) REFERENCES `Events` (`Id`) ON DELETE CASCADE, `FrameId` int(10) unsigned NOT NULL default '0', `PixelDiff` tinyint(3) unsigned NOT NULL default '0', `AlarmPixels` int(10) unsigned NOT NULL default '0', @@ -704,6 +708,7 @@ DROP TABLE IF EXISTS `Zones`; CREATE TABLE `Zones` ( `Id` int(10) unsigned NOT NULL auto_increment, `MonitorId` int(10) unsigned NOT NULL default '0', + FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE, `Name` varchar(64) NOT NULL default '', `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive','Privacy') NOT NULL default 'Active', `Units` enum('Pixels','Percent') NOT NULL default 'Pixels', From 59884375fa5df340daa1cb9dbf245111aadda7bc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 09:23:46 -0400 Subject: [PATCH 065/169] Add references permission so that our zmupdate can add foreign keys --- distros/beowulf/zoneminder.postinst | 4 ++-- distros/ubuntu1604/zoneminder.postinst | 2 +- distros/ubuntu2004/zoneminder.postinst | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/distros/beowulf/zoneminder.postinst b/distros/beowulf/zoneminder.postinst index 603786ff6..032595355 100644 --- a/distros/beowulf/zoneminder.postinst +++ b/distros/beowulf/zoneminder.postinst @@ -39,9 +39,9 @@ if [ "$1" = "configure" ]; then exit 1; fi # This creates the user. - echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql + echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute, REFERENCES on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql else - echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql + echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute, REFERENCES on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql fi zmupdate.pl --nointeractive diff --git a/distros/ubuntu1604/zoneminder.postinst b/distros/ubuntu1604/zoneminder.postinst index 7b7af708b..d89ccf531 100644 --- a/distros/ubuntu1604/zoneminder.postinst +++ b/distros/ubuntu1604/zoneminder.postinst @@ -68,7 +68,7 @@ if [ "$1" = "configure" ]; then echo "CREATE USER '${ZM_DB_USER}'@localhost IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql fi echo "Updating permissions" - echo "grant lock tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql + echo "GRANT LOCK TABLES,ALTER,DROP,SELECT,INSERT,UPDATE,DELETE,CREATE,INDEX,ALTER ROUTINE,CREATE ROUTINE, TRIGGER,EXECUTE,REFERENCES ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql zmupdate.pl --nointeractive zmupdate.pl --nointeractive -f diff --git a/distros/ubuntu2004/zoneminder.postinst b/distros/ubuntu2004/zoneminder.postinst index a8b8eaf51..a50d7cf2e 100644 --- a/distros/ubuntu2004/zoneminder.postinst +++ b/distros/ubuntu2004/zoneminder.postinst @@ -26,7 +26,7 @@ create_update_user () { echo "CREATE USER '${ZM_DB_USER}'@${ZM_DB_HOST} IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql fi echo "Updating permissions" - echo "GRANT LOCK tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine,trigger,execute ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@${ZM_DB_HOST};" | mysql --defaults-file=/etc/mysql/debian.cnf mysql + echo "GRANT LOCK tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine,trigger,execute,REFERENCES ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@${ZM_DB_HOST};" | mysql --defaults-file=/etc/mysql/debian.cnf mysql } update_db () { From 43b7021f9cd3a0b719c721cb9f4c95e7827e55b6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 12:38:44 -0400 Subject: [PATCH 066/169] ALTER Events.Id to BIGINT. This update got lost at somepoint. Add FOREIGN KEYS to Frames, Stats and Zones tables --- db/zm_update-1.35.11.sql | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 db/zm_update-1.35.11.sql diff --git a/db/zm_update-1.35.11.sql b/db/zm_update-1.35.11.sql new file mode 100644 index 000000000..e0257c184 --- /dev/null +++ b/db/zm_update-1.35.11.sql @@ -0,0 +1,22 @@ + +/* Change Id type to BIGINT. */ +ALTER TABLE Events MODIFY Id bigint unsigned NOT NULL auto_increment; + +/* Add FOREIGN KEYS After deleting lost records */ +DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events); +ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE; + +/* Add FOREIGN KEYS After deleting lost records */ +DELETE FROM Stats WHERE EventId NOT IN (SELECT Id FROM Events); +ALTER TABLE Stats ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE; + +DELETE FROM Stats WHERE MonitorId NOT IN (SELECT Id FROM Monitors); +ALTER TABLE Stats ADD FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE; + +DELETE FROM Stats WHERE ZoneId NOT IN (SELECT Id FROM Zones); +ALTER TABLE Stats ADD FOREIGN KEY (`ZoneId`) REFERENCES `Zones` (`Id`) ON DELETE CASCADE; + +/* Add FOREIGN KEYS After deleting lost records */ +DELETE FROM Zones WHERE MonitorId NOT IN (SELECT Id FROM Monitors); +ALTER TABLE Zones ADD FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE; + From 4c92c99ba17e3b4107c8d40230a69214e926dc26 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 12:39:50 -0400 Subject: [PATCH 067/169] bump version for 1.35.11 db updates --- distros/redhat/zoneminder.spec | 2 +- version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 5c19dd0c0..3a4d45de8 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -28,7 +28,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.35.10 +Version: 1.35.11 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/version b/version index a0b71b46f..5f1e3b58b 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.35.10 +1.35.11 From b3a28b2ba20b858eea71be965bbdeae8662a3cb8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 12:49:03 -0400 Subject: [PATCH 068/169] fix confusion in syslog reporting web_php when the error was actually web_js --- web/includes/logger.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/includes/logger.php b/web/includes/logger.php index fb7d58f93..ab59b412b 100644 --- a/web/includes/logger.php +++ b/web/includes/logger.php @@ -408,10 +408,10 @@ class Logger { } } - $message = $code.' ['.$string.']'; if ( $level <= $this->syslogLevel ) - syslog( self::$syslogPriorities[$level], $message ); + syslog(self::$syslogPriorities[$level], $message); + $message = $code.' ['.$string.']'; if ( $level <= $this->databaseLevel ) { try { global $dbConn; From 686f793d097973c15f62d89a670c9cf2fb1d648c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 12:49:39 -0400 Subject: [PATCH 069/169] fix truth value for ZM_OPT_USE_GEOLOCATION --- web/skins/classic/views/js/monitor.js.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/monitor.js.php b/web/skins/classic/views/js/monitor.js.php index cc61270d0..bdcc17554 100644 --- a/web/skins/classic/views/js/monitor.js.php +++ b/web/skins/classic/views/js/monitor.js.php @@ -1,4 +1,4 @@ -var ZM_OPT_USE_GEOLOCATION = ''; +var ZM_OPT_USE_GEOLOCATION = '' == '1' ? true : false; Date: Wed, 28 Oct 2020 12:55:32 -0400 Subject: [PATCH 070/169] Add Locking to filters, bump db to 1.35.12. --- db/zm_update-1.35.12.sql | 18 ++++++++++++++++++ distros/redhat/zoneminder.spec | 2 +- version | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 db/zm_update-1.35.12.sql diff --git a/db/zm_update-1.35.12.sql b/db/zm_update-1.35.12.sql new file mode 100644 index 000000000..b8c54f713 --- /dev/null +++ b/db/zm_update-1.35.12.sql @@ -0,0 +1,18 @@ +-- +-- Update Filters table to have a LockRows Column +-- + +SELECT 'Checking for LockRows in Filters'; +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Filters' + AND table_schema = DATABASE() + AND column_name = 'LockRows' + ) > 0, +"SELECT 'Column LockRows already exists in Filters'", +"ALTER TABLE Filters ADD COLUMN `LockRows` tinyint(1) unsigned NOT NULL default '0' AFTER `Concurrent`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 3a4d45de8..eefba559d 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -28,7 +28,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.35.11 +Version: 1.35.12 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/version b/version index 5f1e3b58b..7d872edd4 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.35.11 +1.35.12 From 9a9f80c15c00a050b991355d9edaf85abcfcae4d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 14:07:29 -0400 Subject: [PATCH 071/169] show which user we are updating permissions for --- distros/ubuntu1604/zoneminder.postinst | 2 +- distros/ubuntu2004/zoneminder.postinst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/ubuntu1604/zoneminder.postinst b/distros/ubuntu1604/zoneminder.postinst index d89ccf531..d4010008a 100644 --- a/distros/ubuntu1604/zoneminder.postinst +++ b/distros/ubuntu1604/zoneminder.postinst @@ -67,7 +67,7 @@ if [ "$1" = "configure" ]; then # This creates the user. echo "CREATE USER '${ZM_DB_USER}'@localhost IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql fi - echo "Updating permissions" + echo "Updating permissions for user ${ZM_DB_USER}@localhost" echo "GRANT LOCK TABLES,ALTER,DROP,SELECT,INSERT,UPDATE,DELETE,CREATE,INDEX,ALTER ROUTINE,CREATE ROUTINE, TRIGGER,EXECUTE,REFERENCES ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql zmupdate.pl --nointeractive diff --git a/distros/ubuntu2004/zoneminder.postinst b/distros/ubuntu2004/zoneminder.postinst index a50d7cf2e..cd147a0e2 100644 --- a/distros/ubuntu2004/zoneminder.postinst +++ b/distros/ubuntu2004/zoneminder.postinst @@ -25,7 +25,7 @@ create_update_user () { # This creates the user. echo "CREATE USER '${ZM_DB_USER}'@${ZM_DB_HOST} IDENTIFIED BY '${ZM_DB_PASS}';" | mysql --defaults-file=/etc/mysql/debian.cnf mysql fi - echo "Updating permissions" + echo "Updating permissions for user ${ZM_DB_USER}@${ZM_DB_HOST}" echo "GRANT LOCK tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine,trigger,execute,REFERENCES ON ${ZM_DB_NAME}.* TO '${ZM_DB_USER}'@${ZM_DB_HOST};" | mysql --defaults-file=/etc/mysql/debian.cnf mysql } From a35c143094aabc0f515281bf47e0137913bcdd02 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Oct 2020 15:01:14 -0400 Subject: [PATCH 072/169] Prevent extra foreign keys from being created and fix we can't delete from Zones. Must be done manually --- db/zm_update-1.35.11.sql | 78 +++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/db/zm_update-1.35.11.sql b/db/zm_update-1.35.11.sql index c1e9aad64..0b51f2ef5 100644 --- a/db/zm_update-1.35.11.sql +++ b/db/zm_update-1.35.11.sql @@ -1,20 +1,74 @@ /* Change Id type to BIGINT. */ +SELECT 'Updating Events.Id to BIGINT'; ALTER TABLE Events MODIFY Id bigint unsigned NOT NULL auto_increment; /* Add FOREIGN KEYS After deleting lost records */ -DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events); -ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE; +SELECT 'Adding foreign key for EventId to Frames'; +set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Frames' and column_name='EventId' and referenced_table_name='Events' and referenced_column_name='Id'); +set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; -/* Add FOREIGN KEYS After deleting lost records */ -DELETE FROM Stats WHERE EventId NOT IN (SELECT Id FROM Events); -ALTER TABLE Stats ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE; +set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for EventId in Frames already exists'", "DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events)"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; -DELETE FROM Stats WHERE MonitorId NOT IN (SELECT Id FROM Monitors); -ALTER TABLE Stats ADD FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE; +set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; -DELETE FROM Stats WHERE ZoneId NOT IN (SELECT Id FROM Zones); -ALTER TABLE Stats ADD FOREIGN KEY (`ZoneId`) REFERENCES `Zones` (`Id`) ON DELETE CASCADE; -/* Add FOREIGN KEYS After deleting lost records */ -DELETE FROM Zones WHERE MonitorId NOT IN (SELECT Id FROM Monitors); -ALTER TABLE Zones ADD FOREIGN KEY (`MonitorId`) REFERENCES `Monitors` (`Id`) ON DELETE CASCADE; +SELECT 'Adding foreign key for EventId to Stats'; +set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='EventId' and referenced_table_name='Events' and referenced_column_name='Id'); +set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for EventId in Stats already exists'", "DELETE FROM Stats WHERE EventId NOT IN (SELECT Id FROM Events);"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Stats ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + + +SELECT 'Adding foreign key for MonitorId to Stats'; +set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='MonitorId' and referenced_table_name='Monitors' and referenced_column_name='Id'); +set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for MonitorId in Stats already exists'", "DELETE FROM Stats WHERE MonitorId NOT IN (SELECT Id FROM Monitors);"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Stats ADD FOREIGN KEY (MonitorId) REFERENCES Monitors (Id) ON DELETE CASCADE"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +SELECT 'Adding foreign key for ZoneId to Stats'; +set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='ZoneId' and referenced_table_name='Zones' and referenced_column_name='Id'); +set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for ZoneId in Stats already exists'", "DELETE FROM Stats WHERE ZoneId NOT IN (SELECT Id FROM Zones);"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Stats ADD FOREIGN KEY (ZoneId) REFERENCES Zones (Id) ON DELETE CASCADE"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +SELECT 'Adding foreign key for MonitorId to Zones'; +set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Zones' and column_name='MonitorId' and referenced_table_name='Monitors' and referenced_column_name='Id'); +set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; + +set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for MonitorId in Zones already exists'", "SELECT 'FOREIGN KEY for MonitorId in Zones does not already exist'"); +set @badzones := (select count(*) FROM Zones WHERE MonitorId NOT IN (SELECT Id FROM Monitors)); +set @sqlstmt := if ( @badzones > 0, "SELECT 'You have Zones with no Monitor record in the Monitors table. Please delete them manually'", "ALTER TABLE Zones ADD FOREIGN KEY (MonitorId) REFERENCES Monitors (Id)"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; From 638a05b2079a5787858f67ee7fb686cab0dc7901 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Oct 2020 09:39:48 -0400 Subject: [PATCH 073/169] Fix totalrows in pagination. Still figuring this out. --- web/ajax/events.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 850628109..d5eb80d24 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -155,11 +155,9 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim foreach ( $advsearch as $col=>$text ) { if ( in_array($col, $columns) ) { - //$text = '%' .$text. '%'; array_push($likes, 'E.'.$col.' LIKE ?'); array_push($query['values'], $text); } else if ( in_array($col, $col_alt) ) { - //$text = '%' .$text. '%'; array_push($likes, 'M.'.$col.' LIKE ?'); array_push($query['values'], $text); } else { @@ -198,7 +196,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $rows = array(); foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { - ZM\Debug("row".print_r($row,true)); $event = new ZM\Event($row); if ( !$filter->test_post_sql_conditions($event) ) { $event->remove_from_cache(); @@ -207,7 +204,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $scale = intval(5*100*ZM_WEB_LIST_THUMB_WIDTH / $event->Width()); $imgSrc = $event->getThumbnailSrc(array(),'&'); $streamSrc = $event->getStreamSrc(array( - 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); + 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&'); // Modify the row data as needed $row['imgHtml'] = '' .validHtmlStr('Event ' .$event->Id()). ''; @@ -225,8 +222,9 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } $data['rows'] = $rows; - $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); - $data['total'] = count($rows); + # total has to be the # of available rows. Not sure what totalNotFiltered is actually used for yet. + $data['totalNotFiltered'] = $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); + #$data['total'] = count($rows); return $data; } ?> From 97f4d9e7a2edbbb54602c8da5ab3e2ea45535137 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Oct 2020 09:40:14 -0400 Subject: [PATCH 074/169] Make the event count and diskspace in the storage row be a link to events for that storage area. --- web/skins/classic/views/options.php | 31 +++++++++++++++++------------ 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index cc8b0b568..a52aca15d 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -279,17 +279,23 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as 'lower(Name)') ) as $Storage ) { + $filter = new ZM\Filter(); + $filter->addTerm(array('attr'=>'StorageId','op'=>'=','val'=>$Storage->Id())); + if ( $user['MonitorIds'] ) { + $filter = $filter->addTerm(array('cnj'=>'and', 'attr'=>'MonitorId', 'op'=>'IN', 'val'=>$user['MonitorIds'])); + } + $str_opt = 'class="storageCol" data-sid="'.$Storage->Id().'"'; ?> - Id()), $canEdit, $str_opt ) ?> - Name()), $canEdit, $str_opt ) ?> - Path()), $canEdit, $str_opt ) ?> - Type()), $canEdit, $str_opt ) ?> - Scheme()), $canEdit, $str_opt ) ?> - Server()->Name()), $canEdit, $str_opt ) ?> + Id()), $canEdit, $str_opt) ?> + Name()), $canEdit, $str_opt) ?> + Path()), $canEdit, $str_opt) ?> + Type()), $canEdit, $str_opt) ?> + Scheme()), $canEdit, $str_opt) ?> + Server()->Name()), $canEdit, $str_opt) ?> disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?> - EventCount().' using '.human_filesize($Storage->event_disk_space()) ?> + querystring(), $Storage->EventCount().' using '.human_filesize($Storage->event_disk_space()) ); ?> EventCount() or !$canEdit ) { ?> disabled="disabled"EventCount() ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/> @@ -302,13 +308,12 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as APIs are disabled. To enable, please turn on OPT_USE_API in Options->System
"; - } - else { + $apiEnabled = dbFetchOne('SELECT Value FROM Config WHERE Name=\'ZM_OPT_USE_API\''); + if ( $apiEnabled['Value'] != '1' ) { + echo '
APIs are disabled. To enable, please turn on OPT_USE_API in Options->System
'; + } else { ?>
From 41e88fad6eb79761429c9971860a2883c7ebc250 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Oct 2020 15:08:14 -0400 Subject: [PATCH 075/169] translate \n to
. Fixes #3064 --- web/ajax/events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index d5eb80d24..200416f92 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -216,7 +216,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndTime'])); $row['Length'] = gmdate('H:i:s', $row['Length'] ); $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; - $row['Notes'] = htmlspecialchars($row['Notes']); + $row['Notes'] = nl2br(htmlspecialchars($row['Notes'])); $row['DiskSpace'] = human_filesize($event->DiskSpace()); $rows[] = $row; } From e4a585eaa328ad85c108efc1bcc8fb9714f7c1a6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Oct 2020 09:18:53 -0400 Subject: [PATCH 076/169] improvements to 1.35.11 db updates --- db/zm_update-1.35.11.sql | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/db/zm_update-1.35.11.sql b/db/zm_update-1.35.11.sql index 0b51f2ef5..3906d8c04 100644 --- a/db/zm_update-1.35.11.sql +++ b/db/zm_update-1.35.11.sql @@ -1,19 +1,26 @@ /* Change Id type to BIGINT. */ -SELECT 'Updating Events.Id to BIGINT'; -ALTER TABLE Events MODIFY Id bigint unsigned NOT NULL auto_increment; +set @exist := (SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'Events' AND COLUMN_NAME = 'Id' and DATA_TYPE='bigint'); + +set @sqlstmt := if( @exist = 0, "ALTER TABLE Events MODIFY Id bigint unsigned NOT NULL auto_increment", "SELECT 'Ok'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; /* Add FOREIGN KEYS After deleting lost records */ -SELECT 'Adding foreign key for EventId to Frames'; set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Frames' and column_name='EventId' and referenced_table_name='Events' and referenced_column_name='Id'); + set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY EventId in Frames already exists'", @sqlstmt); +set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for EventId to Frames", @sqlstmt); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for EventId in Frames already exists'", "DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events)"); +set @sqlstmt := if( @exist != 0, "SELECT '.'", "SELECT 'Deleting unlinked Frames'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; - -set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE"); +set @sqlstmt := if( @exist != 0, "SELECT '.'", "DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events)"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; +set @sqlstmt := if( @exist != 0, "SELECT 'Ok'", "ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; @@ -21,6 +28,8 @@ EXECUTE stmt; SELECT 'Adding foreign key for EventId to Stats'; set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='EventId' and referenced_table_name='Events' and referenced_column_name='Id'); set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY already EventId in Stats already exists'", @sqlstmt); +set @sqlstmt := if( @exist = 0, "SELECT 'Adding FOREIGN KEY for EventId to Stats'", @sqlstmt); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; From 65df84ef7efe0bad794ad5cdc99145da4a901f48 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Oct 2020 11:49:00 -0400 Subject: [PATCH 077/169] Make ZoneMinder::Event::delete aware of transactions --- scripts/ZoneMinder/lib/ZoneMinder/Event.pm | 24 ++++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 0af41b2ca..985ac71f3 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -349,6 +349,10 @@ sub GenerateVideo { return; } # end sub GenerateVideo +# Note about transactions, this function may be called with rows locked and hence in a transaction. +# So we will detect if we are in a transaction, and if not, start one. We will NOT do rollback or +# commits unless we started the transaction. + sub delete { my $event = $_[0]; @@ -378,23 +382,25 @@ sub delete { Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime} from ".$event->Path()); $ZoneMinder::Database::dbh->ping(); - $ZoneMinder::Database::dbh->begin_work(); - #$event->lock_and_load(); + my $in_transaction = $ZoneMinder::Database::dbh->{AutoCommit} ? 0 : 1; - ZoneMinder::Database::zmDbDo('DELETE FROM Frames WHERE EventId=?', $$event{Id}); - if ( $ZoneMinder::Database::dbh->errstr() ) { - $ZoneMinder::Database::dbh->commit(); - return; - } + $ZoneMinder::Database::dbh->begin_work() if ! $in_transaction; + + # Going to delete in order of least value to greatest value. Stats is least and references Frames ZoneMinder::Database::zmDbDo('DELETE FROM Stats WHERE EventId=?', $$event{Id}); if ( $ZoneMinder::Database::dbh->errstr() ) { - $ZoneMinder::Database::dbh->commit(); + $ZoneMinder::Database::dbh->commit() if ! $in_transaction; + return; + } + ZoneMinder::Database::zmDbDo('DELETE FROM Frames WHERE EventId=?', $$event{Id}); + if ( $ZoneMinder::Database::dbh->errstr() ) { + $ZoneMinder::Database::dbh->commit() if ! $in_transaction; return; } # Do it individually to avoid locking up the table for new events ZoneMinder::Database::zmDbDo('DELETE FROM Events WHERE Id=?', $$event{Id}); - $ZoneMinder::Database::dbh->commit(); + $ZoneMinder::Database::dbh->commit() if ! $in_transaction; } if ( ( $in_zmaudit or (!$Config{ZM_OPT_FAST_DELETE})) and $event->Storage()->DoDelete() ) { From 5fadd366e7f00596835c020c1f09a62a2ee7cfe9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Oct 2020 11:50:03 -0400 Subject: [PATCH 078/169] Always setup Logging SIG handlers. Implement SIGUSR1 and SIGUSR2 handling to match c++ side behaviour. Fixes #3057 --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 801dcf199..cf5a0b508 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -504,9 +504,9 @@ sub openFile { $LOGFILE->autoflush() if $this->{autoFlush}; my $webUid = (getpwnam($ZoneMinder::Config::Config{ZM_WEB_USER}))[2]; - Error("Can't get uid for $ZoneMinder::Config::Config{ZM_WEB_USER}") if ! defined $webUid; + Error('Can\'t get uid for '.$ZoneMinder::Config::Config{ZM_WEB_USER}) if ! defined $webUid; my $webGid = (getgrnam($ZoneMinder::Config::Config{ZM_WEB_GROUP}))[2]; - Error("Can't get gid for $ZoneMinder::Config::Config{ZM_WEB_USER}") if ! defined $webGid; + Error('Can\'t get gid for '.$ZoneMinder::Config::Config{ZM_WEB_USER}) if ! defined $webGid; if ( $> == 0 ) { # If we are root, we want to make sure that www-data or whatever owns the file chown($webUid, $webGid, $this->{logFile} ) or @@ -610,6 +610,7 @@ sub logInit( ;@ ) { my %options = @_ ? @_ : (); $logger = ZoneMinder::Logger->new() if !$logger; $logger->initialise(%options); + logSetSignal(); } sub logReinit { @@ -626,12 +627,26 @@ sub logHupHandler { $do_log_rotate = 1; } +sub logUSR1Handler { + $logger->level($logger->level()+1); + Info('Logger - Level changed to '. $logger->level() . '=>'.$codes{$logger->level()}); +} + +sub logUSR2Handler { + $logger->level($logger->level()-1); + Info('Logger - Level changed to '. $logger->level() . '=>'.$codes{$logger->level()}); +} + sub logSetSignal { $SIG{HUP} = \&logHupHandler; + $SIG{USR1} = \&logUSR1Handler; + $SIG{USR2} = \&logUSR2Handler; } sub logClearSignal { $SIG{HUP} = 'DEFAULT'; + $SIG{USR1} = 'DEFAULT'; + $SIG{USR2} = 'DEFAULT'; } sub logLevel { From e5097d9466150334476f55d2e3517609dd526c40 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Oct 2020 11:50:16 -0400 Subject: [PATCH 079/169] code style --- src/zm_signal.cpp | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/zm_signal.cpp b/src/zm_signal.cpp index 81012c07e..2756802a3 100644 --- a/src/zm_signal.cpp +++ b/src/zm_signal.cpp @@ -29,15 +29,13 @@ bool zm_reload = false; bool zm_terminate = false; -RETSIGTYPE zm_hup_handler(int signal) -{ +RETSIGTYPE zm_hup_handler(int signal) { // Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes. //Info("Got signal %d (%s), reloading", signal, strsignal(signal)); zm_reload = true; } -RETSIGTYPE zm_term_handler(int signal) -{ +RETSIGTYPE zm_term_handler(int signal) { // Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes. //Info("Got signal %d (%s), exiting", signal, strsignal(signal)); zm_terminate = true; @@ -55,8 +53,7 @@ RETSIGTYPE zm_die_handler(int signal) #if ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) void *ip = nullptr; void *cr2 = nullptr; - if (info && context) { - + if ( info && context ) { Debug(1, "Signal information: number %d code %d errno %d pid %d uid %d status %d", signal, info->si_code, info->si_errno, info->si_pid, @@ -79,7 +76,7 @@ RETSIGTYPE zm_die_handler(int signal) #endif // defined(__x86_64__) // Print the signal address and instruction pointer if available - if (ip) { + if ( ip ) { Error("Signal address is %p, from %p", cr2, ip); } else { Error("Signal address is %p, no instruction pointer", cr2); @@ -115,8 +112,7 @@ RETSIGTYPE zm_die_handler(int signal) exit(signal); } -void zmSetHupHandler(SigHandler * handler) -{ +void zmSetHupHandler(SigHandler * handler) { sigset_t block_set; sigemptyset(&block_set); struct sigaction action, old_action; @@ -127,8 +123,7 @@ void zmSetHupHandler(SigHandler * handler) sigaction(SIGHUP, &action, &old_action); } -void zmSetTermHandler(SigHandler * handler) -{ +void zmSetTermHandler(SigHandler * handler) { sigset_t block_set; sigemptyset(&block_set); struct sigaction action, old_action; @@ -141,8 +136,7 @@ void zmSetTermHandler(SigHandler * handler) sigaction(SIGQUIT, &action, &old_action); } -void zmSetDieHandler(SigHandler * handler) -{ +void zmSetDieHandler(SigHandler * handler) { sigset_t block_set; sigemptyset(&block_set); struct sigaction action, old_action; @@ -163,19 +157,16 @@ void zmSetDieHandler(SigHandler * handler) sigaction(SIGFPE, &action, &old_action); } -void zmSetDefaultHupHandler() -{ +void zmSetDefaultHupHandler() { zmSetHupHandler((SigHandler *) zm_hup_handler); } -void zmSetDefaultTermHandler() -{ +void zmSetDefaultTermHandler() { zmSetTermHandler((SigHandler *) zm_term_handler); } -void zmSetDefaultDieHandler() -{ - if (config.dump_cores) { +void zmSetDefaultDieHandler() { + if ( config.dump_cores ) { // Do nothing } else { zmSetDieHandler((SigHandler *) zm_die_handler); From f7d23ce23bc4523d1a7d3658e124243e42379729 Mon Sep 17 00:00:00 2001 From: jahegu Date: Fri, 30 Oct 2020 17:57:28 +0100 Subject: [PATCH 080/169] Update zm_update-1.35.11.sql Missing " ' " simbol that generates a MariaDB problem: ERROR 1064 (42000) at line 14: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''Adding foreign key for EventId to Frames' at line 1 --- db/zm_update-1.35.11.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/zm_update-1.35.11.sql b/db/zm_update-1.35.11.sql index 3906d8c04..ad73b7bf4 100644 --- a/db/zm_update-1.35.11.sql +++ b/db/zm_update-1.35.11.sql @@ -10,7 +10,7 @@ set @exist := (select count(*) FROM information_schema.key_column_usage where ta set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY EventId in Frames already exists'", @sqlstmt); -set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for EventId to Frames", @sqlstmt); +set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for EventId to Frames'", @sqlstmt); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; From a63600ccefdec8652ec213c3e2b85aea7fedbd04 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Oct 2020 16:09:24 -0400 Subject: [PATCH 081/169] remove dead code --- src/zm_logger.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 29361b5a9..006eacbf4 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -43,18 +43,6 @@ Logger *Logger::smInstance = nullptr; Logger::StringMap Logger::smCodes; Logger::IntMap Logger::smSyslogPriorities; -#if 0 -static void subtractTime( struct timeval * const tp1, struct timeval * const tp2 ) { - tp1->tv_sec -= tp2->tv_sec; - if ( tp1->tv_usec <= tp2->tv_usec ) { - tp1->tv_sec--; - tp1->tv_usec = 1000000 - (tp2->tv_usec - tp1->tv_usec); - } else { - tp1->tv_usec = tp1->tv_usec - tp2->tv_usec; - } -} -#endif - void Logger::usrHandler(int sig) { Logger *logger = fetch(); if ( sig == SIGUSR1 ) From 5047c28157fef1581609acd74f2af0db4cebf9dd Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 31 Oct 2020 11:26:29 -0500 Subject: [PATCH 082/169] attempt to fix totalnotfiltered --- web/ajax/events.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 200416f92..1f8e71f1a 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -222,9 +222,14 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } $data['rows'] = $rows; - # total has to be the # of available rows. Not sure what totalNotFiltered is actually used for yet. - $data['totalNotFiltered'] = $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); - #$data['total'] = count($rows); + # totalNotFiltered must equal total, except when either search bar has been used + $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); + if ( $search != '' || count($advsearch) ) { + $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'.$where , 'Total', $wherevalues); + } else { + $data['total'] = $data['totalNotFiltered']; + } + return $data; } ?> From 30e0e49ee73423742dfe49dcf0cec3611dc5bf0b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 31 Oct 2020 14:09:47 -0400 Subject: [PATCH 083/169] Fix total rows when using search --- web/ajax/events.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 200416f92..c8008e8a2 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -181,6 +181,9 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim if ( $where ) $where = ' WHERE '.$where; + # total has to be the # of available rows. Not sure what totalNotFiltered is actually used for yet. + $data['totalNotFiltered'] = $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'. $where, 'Total', $query['values']); + $sort = $sort == 'Monitor' ? 'M.Name' : 'E.'.$sort; $col_str = 'E.*, M.Name AS Monitor'; $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; @@ -195,6 +198,10 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } $rows = array(); + $results = dbFetchAll($query['sql'], NULL, $query['values']); + if ( ! $results ) { + return $data; + } foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { $event = new ZM\Event($row); if ( !$filter->test_post_sql_conditions($event) ) { @@ -222,8 +229,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } $data['rows'] = $rows; - # total has to be the # of available rows. Not sure what totalNotFiltered is actually used for yet. - $data['totalNotFiltered'] = $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); #$data['total'] = count($rows); return $data; } From 824f38c74671f0fe3bf9d3ec102c13003b39484e Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 1 Nov 2020 08:05:53 -0600 Subject: [PATCH 084/169] hide settings buttons rather than disable for non Local monitors --- web/skins/classic/views/js/watch.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 176c85822..23629514e 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -946,7 +946,8 @@ function initPage() { }); // Only enable the settings button for local cameras - settingsBtn.prop('disabled', !(monitorType == 'Local' && canViewControl)); + settingsBtn.prop('disabled', !canViewControl); + if ( monitorType != 'Local' ) settingsBtn.hide(); } // initPage // Kick everything off From 1257a7ea374c81a78bbeda13e2db6c1e2d7d5e20 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 16:11:19 -0500 Subject: [PATCH 085/169] improvements reported by cppcheck --- src/zm_comms.h | 6 +++--- src/zm_config.h | 5 +++-- src/zm_coord.h | 12 ++++++------ src/zm_db.h | 2 +- src/zm_event.cpp | 4 +++- src/zm_event.h | 8 ++++---- src/zm_exception.h | 32 +++++++++++++------------------- src/zm_fifo.h | 13 ++++++++++--- src/zm_local_camera.h | 20 ++++++++++---------- src/zm_logger.h | 4 ++-- src/zm_mem_utils.h | 4 ++-- src/zm_monitor.h | 12 ++++++------ src/zm_packetqueue.h | 2 +- src/zm_time.h | 2 ++ src/zm_user.h | 2 +- src/zmu.cpp | 30 +++++++++++++++--------------- 16 files changed, 82 insertions(+), 76 deletions(-) diff --git a/src/zm_comms.h b/src/zm_comms.h index 46face33c..a5af97dd5 100644 --- a/src/zm_comms.h +++ b/src/zm_comms.h @@ -49,7 +49,7 @@ protected: const int &mWd; protected: - CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd ) { + CommsBase(const int &rd, const int &wd) : mRd(rd), mWd(wd) { } virtual ~CommsBase() { } @@ -62,10 +62,10 @@ public: public: int getReadDesc() const { - return( mRd ); + return mRd; } int getWriteDesc() const { - return( mWd ); + return mWd; } int getMaxDesc() const { return( mRd>mWd?mRd:mWd ); diff --git a/src/zm_config.h b/src/zm_config.h index d348f38e9..687ac430c 100644 --- a/src/zm_config.h +++ b/src/zm_config.h @@ -112,8 +112,9 @@ public: double DecimalValue() const; const char *StringValue() const; - ConfigItem &operator=(const ConfigItem item) { - Copy(item);return *this; + ConfigItem &operator=(const ConfigItem &item) { + Copy(item); + return *this; } inline operator bool() const { return BooleanValue(); diff --git a/src/zm_coord.h b/src/zm_coord.h index c6234fb1c..bb49c2f8b 100644 --- a/src/zm_coord.h +++ b/src/zm_coord.h @@ -48,12 +48,12 @@ public: return( result ); } - inline bool operator==( const Coord &coord ) { return( x == coord.x && y == coord.y ); } - inline bool operator!=( const Coord &coord ) { return( x != coord.x || y != coord.y ); } - inline bool operator>( const Coord &coord ) { return( x > coord.x && y > coord.y ); } - inline bool operator>=( const Coord &coord ) { return( !(operator<(coord)) ); } - inline bool operator<( const Coord &coord ) { return( x < coord.x && y < coord.y ); } - inline bool operator<=( const Coord &coord ) { return( !(operator>(coord)) ); } + inline bool operator==( const Coord &coord ) const { return( x == coord.x && y == coord.y ); } + inline bool operator!=( const Coord &coord ) const { return( x != coord.x || y != coord.y ); } + inline bool operator>( const Coord &coord ) const { return( x > coord.x && y > coord.y ); } + inline bool operator>=( const Coord &coord ) const { return( !(operator<(coord)) ); } + inline bool operator<( const Coord &coord ) const { return( x < coord.x && y < coord.y ); } + inline bool operator<=( const Coord &coord ) const { return( !(operator>(coord)) ); } inline Coord &operator+=( const Coord &coord ) { x += coord.x; y += coord.y; return( *this ); } inline Coord &operator-=( const Coord &coord ) { x -= coord.x; y -= coord.y; return( *this ); } diff --git a/src/zm_db.h b/src/zm_db.h index 11fc9faaa..f9f168cd0 100644 --- a/src/zm_db.h +++ b/src/zm_db.h @@ -28,7 +28,7 @@ class zmDbRow { MYSQL_RES *result_set; MYSQL_ROW row; public: - zmDbRow() { result_set = nullptr; row = nullptr; }; + zmDbRow() : result_set(nullptr), row(nullptr) { }; MYSQL_RES *fetch( const char *query ); zmDbRow( MYSQL_RES *, MYSQL_ROW *row ); ~zmDbRow(); diff --git a/src/zm_event.cpp b/src/zm_event.cpp index b201f5c86..a342d91a7 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -571,6 +571,7 @@ void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, str void Event::WriteDbFrames() { char *frame_insert_values_ptr = (char *)&frame_insert_sql + 90; // 90 == strlen(frame_insert_sql); + Debug(1, "Inserting %d frames", frame_data.size()); while ( frame_data.size() ) { Frame *frame = frame_data.front(); frame_data.pop(); @@ -586,8 +587,9 @@ void Event::WriteDbFrames() { frame->score); delete frame; } - *(frame_insert_values_ptr-1) = '\0'; // The -2 is for the extra , added for values above + *(frame_insert_values_ptr-1) = '\0'; // The -1 is for the extra , added for values above db_mutex.lock(); + Debug(1, "SQL: %s", frame_insert_sql); int rc = mysql_query(&dbconn, frame_insert_sql); db_mutex.unlock(); diff --git a/src/zm_event.h b/src/zm_event.h index 8c44af1f2..ff709e5c6 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -113,14 +113,14 @@ class Event { ~Event(); uint64_t Id() const { return id; } - const std::string &Cause() { return cause; } + const std::string &Cause() const { return cause; } int Frames() const { return frames; } int AlarmFrames() const { return alarm_frames; } const struct timeval &StartTime() const { return start_time; } const struct timeval &EndTime() const { return end_time; } - struct timeval &StartTime() { return start_time; } - struct timeval &EndTime() { return end_time; } + struct timeval &StartTime() const { return start_time; } + struct timeval &EndTime() const { return end_time; } bool SendFrameImage( const Image *image, bool alarm_frame=false ); bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ); @@ -146,7 +146,7 @@ class Event { return Event::getSubPath( localtime( time ) ); } - const char* getEventFile(void) { + const char* getEventFile(void) const { return video_file.c_str(); } diff --git a/src/zm_exception.h b/src/zm_exception.h index a02653b88..1bceeed8a 100644 --- a/src/zm_exception.h +++ b/src/zm_exception.h @@ -22,8 +22,7 @@ #include -class Exception -{ +class Exception { protected: typedef enum { INFO, WARNING, ERROR, FATAL } Severity; @@ -32,33 +31,28 @@ protected: Severity mSeverity; public: - Exception( const std::string &message, Severity severity=ERROR ) : mMessage( message ), mSeverity( severity ) + explicit Exception(const std::string &message, const Severity severity=ERROR) : + mMessage(message), + mSeverity(severity) { } -public: - const std::string &getMessage() const - { - return( mMessage ); + const std::string &getMessage() const { + return mMessage; } - Severity getSeverity() const - { - return( mSeverity ); + Severity getSeverity() const { + return mSeverity; } - bool isInfo() const - { - return( mSeverity == INFO ); + bool isInfo() const { + return mSeverity == INFO; } - bool isWarning() const - { + bool isWarning() const { return( mSeverity == WARNING ); } - bool isError() const - { + bool isError() const { return( mSeverity == ERROR ); } - bool isFatal() const - { + bool isFatal() const { return( mSeverity == FATAL ); } }; diff --git a/src/zm_fifo.h b/src/zm_fifo.h index 065fd569c..abd666891 100644 --- a/src/zm_fifo.h +++ b/src/zm_fifo.h @@ -68,19 +68,26 @@ class FifoStream : public StreamBase { ); protected: - typedef enum { MJPEG, RAW } StreamType; + typedef enum { UNKNOWN, MJPEG, RAW } StreamType; StreamType stream_type; bool sendMJEGFrames(); bool sendRAWFrames(); void processCommand(const CmdMsg *msg) {} public: - FifoStream() {} + FifoStream() : + stream_path(nullptr), + fd(0), + total_read(0), + bytes_read(0), + frame_count(0), + stream_type(UNKNOWN) + {} static void fifo_create_if_missing( const char * path, bool delete_fake_fifo = true); void setStreamStart(const char * path); void setStreamStart(int monitor_id, const char * format); - void runStream(); + void runStream() override; }; #endif // ZM_FIFO_H diff --git a/src/zm_local_camera.h b/src/zm_local_camera.h index d06631c23..f4fb8bd36 100644 --- a/src/zm_local_camera.h +++ b/src/zm_local_camera.h @@ -153,17 +153,17 @@ public: int Palette() const { return( palette ); } int Extras() const { return( extras ); } - int Brightness( int p_brightness=-1 ); - int Hue( int p_hue=-1 ); - int Colour( int p_colour=-1 ); - int Contrast( int p_contrast=-1 ); + int Brightness( int p_brightness=-1 ) override; + int Hue( int p_hue=-1 ) override; + int Colour( int p_colour=-1 ) override; + int Contrast( int p_contrast=-1 ) override; - int PrimeCapture(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); - int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) {return(0);}; - int Close() { return 0; }; + int PrimeCapture()override ; + int PreCapture()override ; + int Capture( Image &image )override ; + int PostCapture()override ; + int CaptureAndRecord( Image &image, timeval recording, char* event_directory ) override {return(0);}; + int Close() override { return 0; }; static bool GetCurrentSettings( const char *device, char *output, int version, bool verbose ); }; diff --git a/src/zm_logger.h b/src/zm_logger.h index 82144a1c9..ad1ac398b 100644 --- a/src/zm_logger.h +++ b/src/zm_logger.h @@ -121,7 +121,7 @@ private: Logger(); ~Logger(); - int limit(int level) { + int limit(const int level) const { if ( level > DEBUG9 ) return DEBUG9; if ( level < NOLOG ) @@ -163,7 +163,7 @@ public: } Level level(Level=NOOPT); - bool debugOn() { + bool debugOn() const { return mEffectiveLevel >= DEBUG1; } diff --git a/src/zm_mem_utils.h b/src/zm_mem_utils.h index 6ef1bdac5..a9e1ab097 100644 --- a/src/zm_mem_utils.h +++ b/src/zm_mem_utils.h @@ -26,7 +26,7 @@ inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) { uint8_t* retptr; #if HAVE_POSIX_MEMALIGN - if ( posix_memalign((void**)&retptr,reqalignment,reqsize) != 0 ) + if ( posix_memalign((void**)&retptr, reqalignment, reqsize) != 0 ) return nullptr; return retptr; @@ -39,7 +39,7 @@ inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) { alloc = retptr + sizeof(void*); - if(((long)alloc % reqalignment) != 0) + if ( ((long)alloc % reqalignment) != 0 ) alloc = alloc + (reqalignment - ((long)alloc % reqalignment)); /* Store a pointer before to the start of the block, just before returned aligned memory */ diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 4b6ec5088..a6d5084bb 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -444,7 +444,7 @@ public: inline Function GetFunction() const { return( function ); } - inline bool Enabled() { + inline bool Enabled() const { if ( function <= MONITOR ) return false; return enabled; @@ -452,17 +452,17 @@ public: inline const char *EventPrefix() const { return event_prefix; } - inline bool Ready() { + inline bool Ready() const { if ( function <= MONITOR ) return false; return( image_count > ready_count ); } - inline bool Active() { + inline bool Active() const { if ( function <= MONITOR ) return false; return( enabled && shared_data->active ); } - inline bool Exif() { + inline bool Exif() const { return embed_exif; } Orientation getOrientation() const; @@ -479,7 +479,7 @@ public: uint64_t GetVideoWriterEventId() const { return video_store_data->current_event; } void SetVideoWriterEventId( unsigned long long p_event_id ) { video_store_data->current_event = p_event_id; } struct timeval GetVideoWriterStartTime() const { return video_store_data->recording; } - void SetVideoWriterStartTime(struct timeval &t) { video_store_data->recording = t; } + void SetVideoWriterStartTime(const struct timeval &t) { video_store_data->recording = t; } unsigned int GetPreEventCount() const { return pre_event_count; }; struct timeval GetVideoBufferDuration() const { return video_buffer_duration; }; @@ -505,7 +505,7 @@ public: inline time_t getStartupTime() const { return shared_data->startup_time; } inline void setStartupTime( time_t p_time ) { shared_data->startup_time = p_time; } - int LabelSize() { return label_size; } + int LabelSize() const { return label_size; } void actionReload(); void actionEnable(); diff --git a/src/zm_packetqueue.h b/src/zm_packetqueue.h index 31fe321cb..cbdf556b4 100644 --- a/src/zm_packetqueue.h +++ b/src/zm_packetqueue.h @@ -31,7 +31,7 @@ extern "C" { } class zm_packetqueue { public: - zm_packetqueue(int max_stream_id); + explicit zm_packetqueue(int max_stream_id); virtual ~zm_packetqueue(); bool queuePacket(AVPacket* packet, struct timeval *timestamp); bool queuePacket(ZMPacket* packet); diff --git a/src/zm_time.h b/src/zm_time.h index 0f7dbc794..490ca1e2c 100644 --- a/src/zm_time.h +++ b/src/zm_time.h @@ -76,7 +76,9 @@ struct DeltaTimeval #define USEC_PER_SEC 1000000 #define MSEC_PER_SEC 1000 +/* extern struct timeval tv; +*/ inline int tvDiffUsec( struct timeval first, struct timeval last ) { diff --git a/src/zm_user.h b/src/zm_user.h index 42fe07554..519ea13de 100644 --- a/src/zm_user.h +++ b/src/zm_user.h @@ -46,7 +46,7 @@ class User { User(); explicit User(const MYSQL_ROW &dbrow); ~User(); - User(User &u) { Copy(u); } + User(const User &u) { Copy(u); } void Copy(const User &u); User& operator=(const User &u) { Copy(u); return *this; diff --git a/src/zmu.cpp b/src/zmu.cpp index bdc467812..30a2a0ce7 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -482,7 +482,7 @@ int main(int argc, char *argv[]) { } // end if ! MONITOR if ( verbose ) { - printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name()); + printf("Monitor %u(%s)\n", monitor->Id(), monitor->Name()); } if ( !monitor->connect() ) { Error("Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name()); @@ -521,19 +521,19 @@ int main(int argc, char *argv[]) { } if ( function & ZMU_READ_IDX ) { if ( verbose ) - printf("Last read index: %d\n", monitor->GetLastReadIndex()); + printf("Last read index: %u\n", monitor->GetLastReadIndex()); else { if ( have_output ) fputc(separator, stdout); - printf("%d", monitor->GetLastReadIndex()); + printf("%u", monitor->GetLastReadIndex()); have_output = true; } } if ( function & ZMU_WRITE_IDX ) { if ( verbose ) { - printf("Last write index: %d\n", monitor->GetLastWriteIndex()); + printf("Last write index: %u\n", monitor->GetLastWriteIndex()); } else { if ( have_output ) fputc(separator, stdout); - printf("%d", monitor->GetLastWriteIndex()); + printf("%u", monitor->GetLastWriteIndex()); have_output = true; } } @@ -558,9 +558,9 @@ int main(int argc, char *argv[]) { if ( function & ZMU_IMAGE ) { if ( verbose ) { if ( image_idx == -1 ) - printf("Dumping last image captured to Monitor%d.jpg", monitor->Id()); + printf("Dumping last image captured to Monitor%u.jpg", monitor->Id()); else - printf("Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id()); + printf("Dumping buffer image %d to Monitor%u.jpg", image_idx, monitor->Id()); if ( scale != -1 ) printf(", scaling by %d%%", scale); printf("\n"); @@ -569,7 +569,7 @@ int main(int argc, char *argv[]) { } if ( function & ZMU_ZONES ) { if ( verbose ) - printf("Dumping zone image to Zones%d.jpg\n", monitor->Id()); + printf("Dumping zone image to Zones%u.jpg\n", monitor->Id()); monitor->DumpZoneImage(zoneString); } if ( function & ZMU_ALARM ) { @@ -735,17 +735,17 @@ int main(int argc, char *argv[]) { Debug(1, "Got %d monitors", mysql_num_rows(result)); printf("%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate"); - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) { - int mon_id = atoi(dbrow[0]); - int function = atoi(dbrow[1]); - if ( !user || user->canAccess(mon_id) ) { - if ( function > 1 ) { - Monitor *monitor = Monitor::Load(mon_id, false, Monitor::QUERY); + for ( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) { + int monitor_id = atoi(dbrow[0]); + int monitor_function = atoi(dbrow[1]); + if ( !user || user->canAccess(monitor_id) ) { + if ( monitor_function > 1 ) { + Monitor *monitor = Monitor::Load(monitor_id, false, Monitor::QUERY); if ( monitor && monitor->connect() ) { struct timeval tv = monitor->GetTimestamp(); printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8" PRIu64 "%8.2f\n", monitor->Id(), - function, + monitor_function, monitor->GetState(), monitor->GetTriggerState(), tv.tv_sec, tv.tv_usec/10000, From 3d795be8640be57c9ed545a39520dddddaa0715a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 1 Nov 2020 15:46:43 -0600 Subject: [PATCH 086/169] remove the thumbnail col if WEB_LIST_THUMBS is off --- web/skins/classic/views/js/events.js | 5 ++++- web/skins/classic/views/js/events.js.php | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index f0bd0b3ac..20bf6b87f 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -68,7 +68,7 @@ function processRows(rows) { row.Frames = '' + row.Frames + ''; row.AlarmFrames = '' + row.AlarmFrames + ''; row.MaxScore = '' + row.MaxScore + ''; - row.Thumbnail = '' + row.imgHtml + ''; + if ( WEB_LIST_THUMBS ) row.Thumbnail = '' + row.imgHtml + ''; }); return rows; @@ -161,6 +161,9 @@ function getEventDetailModal(eid) { } function initPage() { + // Remove the thumbnail column from the DOM if thumbnails are off globally + if ( !WEB_LIST_THUMBS ) $j('th[data-field="Thumbnail"]').remove(); + // Load the delete confirmation modal into the DOM getDelConfirmModal(); diff --git a/web/skins/classic/views/js/events.js.php b/web/skins/classic/views/js/events.js.php index 48f405dd7..207a6745e 100644 --- a/web/skins/classic/views/js/events.js.php +++ b/web/skins/classic/views/js/events.js.php @@ -11,3 +11,4 @@ var archivedString = ""; var emailedString = ""; var yesString = ""; var noString = ""; +var WEB_LIST_THUMBS = ; From f79602d638ae1f4b472fe3c7bf66a499afac9181 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 17:14:04 -0500 Subject: [PATCH 087/169] cppcheck improvements. Use %u instead of %d where appropriate. Move sql def to block where it is used --- src/zm_event.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index a342d91a7..730d23b98 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -88,7 +88,9 @@ Event::Event( char sql[ZM_SQL_MED_BUFSIZ]; struct tm *stime = localtime(&start_time.tv_sec); - snprintf(sql, sizeof(sql), "INSERT INTO Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme ) VALUES ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '%s', %d, '%s' )", + snprintf(sql, sizeof(sql), "INSERT INTO Events " + "( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme )" + " VALUES ( %u, %u, 'New Event', from_unixtime( %ld ), %u, %u, '%s', '%s', %u, %d, %d, '%s', %d, '%s' )", monitor->Id(), storage->Id(), start_time.tv_sec, @@ -684,7 +686,6 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a bool db_frame = ( frame_type != BULK ) || (frames==1) || ((frames%config.bulk_frame_interval)==0) ; if ( db_frame ) { - static char sql[ZM_SQL_MED_BUFSIZ]; // The idea is to write out 1/sec frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time, score)); @@ -694,6 +695,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a WriteDbFrames(); last_db_frame = frames; + static char sql[ZM_SQL_MED_BUFSIZ]; snprintf(sql, sizeof(sql), "UPDATE Events SET Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64, ( delta_time.positive?"":"-" ), From 82c34361550ab0c388446df89e698d591d27bb62 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 17:14:44 -0500 Subject: [PATCH 088/169] cppcheck improvements. Remove non-const StartTime and EndTime. We will remove the dirty hack use in zm_monitor. --- src/zm_event.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/zm_event.h b/src/zm_event.h index ff709e5c6..ab837658e 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -119,17 +119,15 @@ class Event { const struct timeval &StartTime() const { return start_time; } const struct timeval &EndTime() const { return end_time; } - struct timeval &StartTime() const { return start_time; } - struct timeval &EndTime() const { return end_time; } bool SendFrameImage( const Image *image, bool alarm_frame=false ); - bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ); + bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ) const; bool WriteFrameVideo( const Image *image, const struct timeval timestamp, VideoWriter* videow ); void updateNotes( const StringSetMap &stringSetMap ); void AddFrames( int n_frames, Image **images, struct timeval **timestamps ); - void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=nullptr ); + void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_image=nullptr ); private: void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ); From 80e54aee663254b9d5bedb1028a2e0b98450b7f1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 17:15:17 -0500 Subject: [PATCH 089/169] cppcheck improvements. Add const and override where we can --- src/zm_eventstream.h | 2 +- src/zm_ffmpeg_input.h | 4 ++-- src/zm_monitorstream.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/zm_eventstream.h b/src/zm_eventstream.h index 5013e5487..be8488486 100644 --- a/src/zm_eventstream.h +++ b/src/zm_eventstream.h @@ -133,7 +133,7 @@ class EventStream : public StreamBase { void setStreamMode( StreamMode p_mode ) { mode = p_mode; } - void runStream(); + void runStream() override; Image *getImage(); private: bool send_file( const char *file_path ); diff --git a/src/zm_ffmpeg_input.h b/src/zm_ffmpeg_input.h index 900f14d4a..35de5edf9 100644 --- a/src/zm_ffmpeg_input.h +++ b/src/zm_ffmpeg_input.h @@ -23,10 +23,10 @@ class FFmpeg_Input { int Close(); AVFrame *get_frame( int stream_id=-1 ); AVFrame *get_frame( int stream_id, double at ); - int get_video_stream_id() { + int get_video_stream_id() const { return video_stream_id; } - int get_audio_stream_id() { + int get_audio_stream_id() const { return audio_stream_id; } diff --git a/src/zm_monitorstream.h b/src/zm_monitorstream.h index 24655b636..20842fa55 100644 --- a/src/zm_monitorstream.h +++ b/src/zm_monitorstream.h @@ -71,7 +71,7 @@ class MonitorStream : public StreamBase { bool setStreamStart(int monitor_id) { return loadMonitor(monitor_id); } - void runStream(); + void runStream() override; }; #endif // ZM_MONITORSTREAM_H From 296f6af7fb707bfc5a81105c9f14656568c8f0ea Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 17:15:42 -0500 Subject: [PATCH 090/169] Remove dirty hack that sets EndTime from monitor. It can get set in event destructor --- src/zm_monitor.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 7a1677d7b..231b02916 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2654,10 +2654,6 @@ bool Monitor::closeEvent() { if ( !event ) return false; - if ( function == RECORD || function == MOCORD ) { - //FIXME Is this neccessary? ENdTime should be set in the destructor - gettimeofday(&(event->EndTime()), nullptr); - } if ( event_delete_thread ) { event_delete_thread->join(); delete event_delete_thread; From 033e749a5756f6246008fb792a99ad455c872982 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 17:16:07 -0500 Subject: [PATCH 091/169] improve code logic/spacing --- src/zms.cpp | 165 ++++++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 82 deletions(-) diff --git a/src/zms.cpp b/src/zms.cpp index 9b661c564..4e77ea4c1 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -95,91 +95,92 @@ int main(int argc, const char *argv[], char **envp) { } const char *query = getenv("QUERY_STRING"); - if ( query ) { - Debug(1, "Query: %s", query); - - char temp_query[1024]; - strncpy(temp_query, query, sizeof(temp_query)-1); - char *q_ptr = temp_query; - char *parms[16]; // Shouldn't be more than this - int parm_no = 0; - while ( (parm_no < 16) && (parms[parm_no] = strtok(q_ptr, "&")) ) { - parm_no++; - q_ptr = nullptr; - } - - for ( int p = 0; p < parm_no; p++ ) { - char *name = strtok(parms[p], "="); - char const *value = strtok(nullptr, "="); - if ( !value ) - value = ""; - if ( !strcmp(name, "source") ) { - source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR; - if ( !strcmp(value, "fifo") ) - source = ZMS_FIFO; - } else if ( !strcmp(name, "mode") ) { - mode = !strcmp(value, "jpeg")?ZMS_JPEG:ZMS_MPEG; - mode = !strcmp(value, "raw")?ZMS_RAW:mode; - mode = !strcmp(value, "zip")?ZMS_ZIP:mode; - mode = !strcmp(value, "single")?ZMS_SINGLE:mode; - } else if ( !strcmp(name, "format") ) { - strncpy( format, value, sizeof(format) ); - } else if ( !strcmp(name, "monitor") ) { - monitor_id = atoi(value); - if ( source == ZMS_UNKNOWN ) - source = ZMS_MONITOR; - } else if ( !strcmp(name, "time") ) { - event_time = atoi(value); - } else if ( !strcmp(name, "event") ) { - event_id = strtoull(value, nullptr, 10); - source = ZMS_EVENT; - } else if ( !strcmp(name, "frame") ) { - frame_id = strtoull(value, nullptr, 10); - source = ZMS_EVENT; - } else if ( !strcmp(name, "scale") ) { - scale = atoi(value); - } else if ( !strcmp(name, "rate") ) { - rate = atoi(value); - } else if ( !strcmp(name, "maxfps") ) { - maxfps = atof(value); - } else if ( !strcmp(name, "bitrate") ) { - bitrate = atoi(value); - } else if ( !strcmp(name, "ttl") ) { - ttl = atoi(value); - } else if ( !strcmp(name, "replay") ) { - if ( !strcmp(value, "gapless") ) { - replay = EventStream::MODE_ALL_GAPLESS; - } else if ( !strcmp(value, "all") ) { - replay = EventStream::MODE_ALL; - } else if ( !strcmp(value, "none") ) { - replay = EventStream::MODE_NONE; - } else if ( !strcmp(value, "single") ) { - replay = EventStream::MODE_SINGLE; - } else { - Error("Unsupported value %s for replay, defaulting to none", value); - } - } else if ( !strcmp(name, "connkey") ) { - connkey = atoi(value); - } else if ( !strcmp(name, "buffer") ) { - playback_buffer = atoi(value); - } else if ( !strcmp(name, "auth") ) { - strncpy(auth, value, sizeof(auth)-1); - } else if ( !strcmp(name, "token") ) { - jwt_token_str = value; - Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str()); - } else if ( !strcmp(name, "user") ) { - username = UriDecode(value); - } else if ( !strcmp(name, "pass") ) { - password = UriDecode(value); - Debug(1, "Have %s for password", password.c_str()); - } else { - Debug(1, "Unknown parameter passed to zms %s=%s", name, value); - } // end if possible parameter names - } // end foreach parm - } else { + if ( query == nullptr ) { Fatal("No query string."); + return 0; } // end if query + Debug(1, "Query: %s", query); + + char temp_query[1024]; + strncpy(temp_query, query, sizeof(temp_query)-1); + char *q_ptr = temp_query; + char *parms[16]; // Shouldn't be more than this + int parm_no = 0; + while ( (parm_no < 16) && (parms[parm_no] = strtok(q_ptr, "&")) ) { + parm_no++; + q_ptr = nullptr; + } + + for ( int p = 0; p < parm_no; p++ ) { + char *name = strtok(parms[p], "="); + char const *value = strtok(nullptr, "="); + if ( !value ) + value = ""; + if ( !strcmp(name, "source") ) { + source = !strcmp(value, "event")?ZMS_EVENT:ZMS_MONITOR; + if ( !strcmp(value, "fifo") ) + source = ZMS_FIFO; + } else if ( !strcmp(name, "mode") ) { + mode = !strcmp(value, "jpeg")?ZMS_JPEG:ZMS_MPEG; + mode = !strcmp(value, "raw")?ZMS_RAW:mode; + mode = !strcmp(value, "zip")?ZMS_ZIP:mode; + mode = !strcmp(value, "single")?ZMS_SINGLE:mode; + } else if ( !strcmp(name, "format") ) { + strncpy(format, value, sizeof(format)-1); + } else if ( !strcmp(name, "monitor") ) { + monitor_id = atoi(value); + if ( source == ZMS_UNKNOWN ) + source = ZMS_MONITOR; + } else if ( !strcmp(name, "time") ) { + event_time = atoi(value); + } else if ( !strcmp(name, "event") ) { + event_id = strtoull(value, nullptr, 10); + source = ZMS_EVENT; + } else if ( !strcmp(name, "frame") ) { + frame_id = strtoull(value, nullptr, 10); + source = ZMS_EVENT; + } else if ( !strcmp(name, "scale") ) { + scale = atoi(value); + } else if ( !strcmp(name, "rate") ) { + rate = atoi(value); + } else if ( !strcmp(name, "maxfps") ) { + maxfps = atof(value); + } else if ( !strcmp(name, "bitrate") ) { + bitrate = atoi(value); + } else if ( !strcmp(name, "ttl") ) { + ttl = atoi(value); + } else if ( !strcmp(name, "replay") ) { + if ( !strcmp(value, "gapless") ) { + replay = EventStream::MODE_ALL_GAPLESS; + } else if ( !strcmp(value, "all") ) { + replay = EventStream::MODE_ALL; + } else if ( !strcmp(value, "none") ) { + replay = EventStream::MODE_NONE; + } else if ( !strcmp(value, "single") ) { + replay = EventStream::MODE_SINGLE; + } else { + Error("Unsupported value %s for replay, defaulting to none", value); + } + } else if ( !strcmp(name, "connkey") ) { + connkey = atoi(value); + } else if ( !strcmp(name, "buffer") ) { + playback_buffer = atoi(value); + } else if ( !strcmp(name, "auth") ) { + strncpy(auth, value, sizeof(auth)-1); + } else if ( !strcmp(name, "token") ) { + jwt_token_str = value; + Debug(1, "ZMS: JWT token found: %s", jwt_token_str.c_str()); + } else if ( !strcmp(name, "user") ) { + username = UriDecode(value); + } else if ( !strcmp(name, "pass") ) { + password = UriDecode(value); + Debug(1, "Have %s for password", password.c_str()); + } else { + Debug(1, "Unknown parameter passed to zms %s=%s", name, value); + } // end if possible parameter names + } // end foreach parm + if ( monitor_id ) { snprintf(log_id_string, sizeof(log_id_string), "zms_m%d", monitor_id); } else { From 5b918e69f14b243a59fc8a9de049827c6a420502 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 17:16:19 -0500 Subject: [PATCH 092/169] spacing --- src/zm_video.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zm_video.cpp b/src/zm_video.cpp index d97c75167..b24905ece 100644 --- a/src/zm_video.cpp +++ b/src/zm_video.cpp @@ -216,7 +216,7 @@ int X264MP4Writer::Open() { int X264MP4Writer::Close() { /* Flush all pending frames */ for ( int i = (x264_encoder_delayed_frames(x264enc) + 1); i > 0; i-- ) { -Debug(1,"Encoding delayed frame"); + Debug(1, "Encoding delayed frame"); if ( x264encodeloop(true) < 0 ) break; } @@ -227,7 +227,7 @@ Debug(1,"Encoding delayed frame"); /* Close MP4 handle */ MP4Close(mp4h); - Debug(1,"Optimising"); + Debug(1, "Optimising"); /* Required for proper HTTP streaming */ MP4Optimize((path + ".incomplete").c_str(), path.c_str()); From 6e3eb922e02287d9b190e1a28fb8e22fb550ccbd Mon Sep 17 00:00:00 2001 From: Matt N Date: Sun, 1 Nov 2020 14:55:08 -0800 Subject: [PATCH 093/169] Use relative symlinks for monitor event directories This way the link continues to work from backups and after the user moves ZM data to a new directory. --- web/includes/actions/monitor.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/includes/actions/monitor.php b/web/includes/actions/monitor.php index 140957046..be17578cf 100644 --- a/web/includes/actions/monitor.php +++ b/web/includes/actions/monitor.php @@ -121,7 +121,8 @@ if ( $action == 'save' ) { } $saferNewName = basename($_REQUEST['newMonitor']['Name']); $link_path = $NewStorage->Path().'/'.$saferNewName; - if ( !symlink($NewStorage->Path().'/'.$mid, $link_path) ) { + // Use a relative path for the target so the link continues to work from backups or directory changes. + if ( !symlink($mid, $link_path) ) { if ( ! ( file_exists($link_path) and is_link($link_path) ) ) { ZM\Warning('Unable to symlink ' . $NewStorage->Path().'/'.$mid . ' to ' . $NewStorage->Path().'/'.$saferNewName); } From 4e80c04d230d082500f29dc2bbac5b27a1f736e0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 1 Nov 2020 18:48:13 -0500 Subject: [PATCH 094/169] fix lack of const to match def --- src/zm_event.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 730d23b98..f5d93f151 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -336,7 +336,7 @@ bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, - bool alarm_frame) { + bool alarm_frame) const { int thisquality = (alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality)) ? From ea4d3ccd7a589cf347bcd3050c60b0fe582c18ba Mon Sep 17 00:00:00 2001 From: Esteban Flores Date: Mon, 2 Nov 2020 01:05:57 -0600 Subject: [PATCH 095/169] Changed "Purge By Age" filter Changed "Purge By Age" filter, the "date" option is not available in v1.34.22. Using "End Date" as the filter parameter works just fine. --- docs/faq.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 56b67d082..1db30e05f 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -27,7 +27,7 @@ After you've done that, you changes will automatically be loaded into zmfilter w Check the ``zmfilter.log`` file to make sure it is running as sometimes missing perl modules mean that it never runs but people don't always realize. **Purge By Age** -To delete events that are older than 7 days, create a new filter with "Date" set to "less than" and a value of "-7 days", sort by "date/time" in "asc"ending order, then enable the checkbox "delete all matches". You can also use a value of week or week and days: "-2 week" or "-2 week 4 day" +To delete events that are older than 7 days, create a new filter with "End Date" set to "less than" and a value of "-7 days", sort by "date/time" in "asc"ending order, then enable the checkbox "delete all matches". You can also use a value of week or week and days: "-2 week" or "-2 week 4 day" Save with 'Run Filter In Background' enabled to have it run automatically. Optional skip archived events: click on the plus sign next to -7 days to add another condition. "and" "archive status" equal to "unarchived only". @@ -534,4 +534,4 @@ The GPL license allows you produce systems based on GPL software provided your s I am having issues with zmNinja and/or Event Notification Server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -zmNinja and the Event Notification Server are 3rd party solutions. The developer maintains exhaustive `documentation and FAQs `__. Please direct your questions there. \ No newline at end of file +zmNinja and the Event Notification Server are 3rd party solutions. The developer maintains exhaustive `documentation and FAQs `__. Please direct your questions there. From ed87ad36b318739e45663f077fe6b984aa66b508 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 12:09:25 -0500 Subject: [PATCH 096/169] missing break --- src/zm_eventstream.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index b8de60e46..05fa647ae 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -424,6 +424,7 @@ void EventStream::processCommand(const CmdMsg *msg) { switch ( replay_rate ) { case -1 * ZM_RATE_BASE : replay_rate = -2 * ZM_RATE_BASE; + break; case -2 * ZM_RATE_BASE : replay_rate = -5 * ZM_RATE_BASE; break; From 492e65c2fdd697bece9e4c196ff7f729a682b7bc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 12:42:30 -0500 Subject: [PATCH 097/169] Add missing PathToAPI --- web/skins/classic/views/options.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index a52aca15d..2be9e9b52 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -231,6 +231,7 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as Url()), $canEdit, $svr_opt ) ?> PathToIndex()), $canEdit, $svr_opt ) ?> PathToZMS()), $canEdit, $svr_opt ) ?> + PathToAPI()), $canEdit, $svr_opt ) ?> Status()), $canEdit, $svr_opt) ?> Id()]), $canEdit, $svr_opt) ?> From 7650e0bf5174180409fcc997e77e08cef40cde59 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 12:43:45 -0500 Subject: [PATCH 098/169] cleanup my totalNotFiltered code. Join Monitors as well as they can be referenced by the filter --- web/ajax/events.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 769bd29d9..e6ec9ec0b 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -181,8 +181,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim if ( $where ) $where = ' WHERE '.$where; - # total has to be the # of available rows. Not sure what totalNotFiltered is actually used for yet. - $data['totalNotFiltered'] = $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'. $where, 'Total', $query['values']); $sort = $sort == 'Monitor' ? 'M.Name' : 'E.'.$sort; $col_str = 'E.*, M.Name AS Monitor'; @@ -229,15 +227,14 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } $data['rows'] = $rows; - if ( 0 ) { # totalNotFiltered must equal total, except when either search bar has been used - $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); + $data['totalNotFiltered'] = dbFetchOne( + 'SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); if ( $search != '' || count($advsearch) ) { - $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'.$where , 'Total', $wherevalues); + $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where , 'Total', $wherevalues); } else { $data['total'] = $data['totalNotFiltered']; } - } return $data; } ?> From 5d32e0faf0865734ab572d143eb32e1fbf279caa Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 12:45:19 -0500 Subject: [PATCH 099/169] cppcheck fixes. Make curr_frame_id signed as we may subtract from it and go < 0 --- src/zm_eventstream.cpp | 31 +++++++++++++++---------------- src/zm_eventstream.h | 6 +++--- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 05fa647ae..6f2ba4197 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -189,13 +189,13 @@ bool EventStream::loadEventData(uint64_t event_id) { if ( storage_path[0] == '/' ) snprintf(event_data->path, sizeof(event_data->path), - "%s/%d/%02d/%02d/%02d/%02d/%02d/%02d", + "%s/%u/%02d/%02d/%02d/%02d/%02d/%02d", storage_path, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec); else snprintf(event_data->path, sizeof(event_data->path), - "%s/%s/%d/%02d/%02d/%02d/%02d/%02d/%02d", + "%s/%s/%u/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec); @@ -203,23 +203,23 @@ bool EventStream::loadEventData(uint64_t event_id) { struct tm *event_time = localtime(&event_data->start_time); if ( storage_path[0] == '/' ) snprintf(event_data->path, sizeof(event_data->path), - "%s/%d/%04d-%02d-%02d/%" PRIu64, + "%s/%u/%04d-%02d-%02d/%" PRIu64, storage_path, event_data->monitor_id, event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday, event_data->event_id); else snprintf(event_data->path, sizeof(event_data->path), - "%s/%s/%d/%04d-%02d-%02d/%" PRIu64, + "%s/%s/%u/%04d-%02d-%02d/%" PRIu64, staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, - event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday, + event_time->tm_year+1900, event_time->tm_mon+1, event_time->tm_mday, event_data->event_id); } else { if ( storage_path[0] == '/' ) - snprintf(event_data->path, sizeof(event_data->path), "%s/%d/%" PRIu64, + snprintf(event_data->path, sizeof(event_data->path), "%s/%u/%" PRIu64, storage_path, event_data->monitor_id, event_data->event_id); else - snprintf(event_data->path, sizeof(event_data->path), "%s/%s/%d/%" PRIu64, + snprintf(event_data->path, sizeof(event_data->path), "%s/%s/%u/%" PRIu64, staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_data->event_id); } @@ -527,7 +527,7 @@ void EventStream::processCommand(const CmdMsg *msg) { if ( offset < 0.0 ) { Warning("Invalid offset, not seeking"); break; - } + } // This should get us close, but not all frames will have the same duration curr_frame_id = (int)(event_data->frame_count*offset/event_data->duration)+1; if ( event_data->frames[curr_frame_id-1].offset > offset ) { @@ -539,10 +539,10 @@ void EventStream::processCommand(const CmdMsg *msg) { } if ( curr_frame_id < 1 ) { curr_frame_id = 1; - } else if ( curr_frame_id > event_data->last_frame_id ) { + } else if ( (unsigned long)curr_frame_id > event_data->last_frame_id ) { curr_frame_id = event_data->last_frame_id; } - + curr_stream_time = event_data->frames[curr_frame_id-1].timestamp; Debug(1, "Got SEEK command, to %f (new current frame id: %d offset %f)", offset, curr_frame_id, event_data->frames[curr_frame_id-1].offset); @@ -795,7 +795,7 @@ bool EventStream::sendFrame(int delta_us) { Error("Unable to get a frame"); return false; } - + Image *send_image = prepareImage(image); static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; int img_buffer_size = 0; @@ -882,7 +882,7 @@ void EventStream::runStream() { // If we are streaming and this frame is due to be sent // frame mod defaults to 1 and if we are going faster than max_fps will get multiplied by 2 // so if it is 2, then we send every other frame, if is it 4 then every fourth frame, etc. - + if ( (frame_mod == 1) || (((curr_frame_id-1)%frame_mod) == 0) ) { send_frame = true; } @@ -964,7 +964,7 @@ void EventStream::runStream() { if ( (mode == MODE_SINGLE) && ( (curr_frame_id < 1 ) || - ((unsigned int)curr_frame_id >= event_data->frame_count) + ((unsigned int)curr_frame_id >= event_data->frame_count) ) ) { Debug(2, "Have mode==MODE_SINGLE and at end of event, looping back to start"); @@ -1055,9 +1055,8 @@ void EventStream::runStream() { closeComms(); } // end void EventStream::runStream() -bool EventStream::send_file(const char * filepath) { +bool EventStream::send_file(const char *filepath) { static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; - int rc; int img_buffer_size = 0; uint8_t *img_buffer = temp_img_buffer; @@ -1085,7 +1084,7 @@ bool EventStream::send_file(const char * filepath) { Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno)); return false; } - rc = zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size); + int rc = zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size); if ( rc == (int)filestat.st_size ) { // Success fclose(fdj); /* Close the file handle */ diff --git a/src/zm_eventstream.h b/src/zm_eventstream.h index be8488486..39daf23d0 100644 --- a/src/zm_eventstream.h +++ b/src/zm_eventstream.h @@ -76,7 +76,7 @@ class EventStream : public StreamBase { StreamMode mode; bool forceEventChange; - unsigned long curr_frame_id; + long curr_frame_id; double curr_stream_time; bool send_frame; struct timeval start; // clock time when started the event @@ -136,8 +136,8 @@ class EventStream : public StreamBase { void runStream() override; Image *getImage(); private: - bool send_file( const char *file_path ); - bool send_buffer( uint8_t * buffer, int size ); + bool send_file(const char *filepath); + bool send_buffer(uint8_t * buffer, int size); Storage *storage; FFmpeg_Input *ffmpeg_input; AVCodecContext *input_codec_context; From a857f677a60b990a95eb280d1accdcd4ee0aa776 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 12:45:48 -0500 Subject: [PATCH 100/169] cppcheck fixes, mostly %d->%u --- src/zm_monitorstream.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index 71a7a66d2..58039b2bf 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -292,7 +292,7 @@ void MonitorStream::processCommand(const CmdMsg *msg) { if ( (nbytes = sendto(sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr))) < 0 ) { //if ( errno != EAGAIN ) { - Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); + Error("Can't sendto on sd %d: %s", sd, strerror(errno)); //exit( -1 ); } } @@ -503,7 +503,7 @@ void MonitorStream::runStream() { const int max_swap_len_suffix = 15; int swap_path_length = staticConfig.PATH_SWAP.length() + 1; // +1 for NULL terminator - int subfolder1_length = snprintf(nullptr, 0, "/zmswap-m%d", monitor->Id()) + 1; + int subfolder1_length = snprintf(nullptr, 0, "/zmswap-m%u", monitor->Id()) + 1; int subfolder2_length = snprintf(nullptr, 0, "/zmswap-q%06d", connkey) + 1; int total_swap_path_length = swap_path_length + subfolder1_length + subfolder2_length; @@ -874,7 +874,7 @@ void MonitorStream::SingleImageRaw(int scale) { } fprintf(stdout, - "Content-Length: %d\r\n" + "Content-Length: %u\r\n" "Content-Type: image/x-rgb\r\n\r\n", snap_image->Size()); fwrite(snap_image->Buffer(), snap_image->Size(), 1, stdout); From 96a9a73320e778bdb07486a5c24cdf9f20e84874 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 2 Nov 2020 14:33:40 -0600 Subject: [PATCH 101/169] roll back events.php --- web/ajax/events.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 769bd29d9..1f8e71f1a 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -181,9 +181,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim if ( $where ) $where = ' WHERE '.$where; - # total has to be the # of available rows. Not sure what totalNotFiltered is actually used for yet. - $data['totalNotFiltered'] = $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'. $where, 'Total', $query['values']); - $sort = $sort == 'Monitor' ? 'M.Name' : 'E.'.$sort; $col_str = 'E.*, M.Name AS Monitor'; $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; @@ -198,10 +195,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } $rows = array(); - $results = dbFetchAll($query['sql'], NULL, $query['values']); - if ( ! $results ) { - return $data; - } foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { $event = new ZM\Event($row); if ( !$filter->test_post_sql_conditions($event) ) { @@ -229,7 +222,6 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } $data['rows'] = $rows; - if ( 0 ) { # totalNotFiltered must equal total, except when either search bar has been used $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); if ( $search != '' || count($advsearch) ) { @@ -237,7 +229,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim } else { $data['total'] = $data['totalNotFiltered']; } - } + return $data; } ?> From bd1d4f954bd39f18db67227430e5053943b46f7f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 15:45:05 -0500 Subject: [PATCH 102/169] Test for EndTime value before using strftime on it. --- web/ajax/events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 1f8e71f1a..fad91683d 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -213,7 +213,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); $row['Cause'] = validHtmlStr($row['Cause']); $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); - $row['EndTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndTime'])); + $row['EndTime'] = $row['EndTime'] ? strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndTime'])) : null; $row['Length'] = gmdate('H:i:s', $row['Length'] ); $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; $row['Notes'] = nl2br(htmlspecialchars($row['Notes'])); From 0f74e24bfc0c74167f881b7a0fc208aaa530a2e4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 15:50:38 -0500 Subject: [PATCH 103/169] Join Monitors as M as well in total and totalNotFiltered queries --- web/ajax/events.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index 1f8e71f1a..833c566d5 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -223,9 +223,9 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $data['rows'] = $rows; # totalNotFiltered must equal total, except when either search bar has been used - $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); + $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'. ($filter->sql() ? ' WHERE '.$filter->sql():''), 'Total'); if ( $search != '' || count($advsearch) ) { - $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table. ' AS E'.$where , 'Total', $wherevalues); + $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where , 'Total', $wherevalues); } else { $data['total'] = $data['totalNotFiltered']; } From b8bd4b6961361aa6a8eb88206d2bc1f7f27e8463 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Nov 2020 16:34:00 -0500 Subject: [PATCH 104/169] Add fallback for now to endtime. Set endtime in AddFramesInternal as well just in case there was never another frame. --- src/zm_event.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index f5d93f151..e762698fa 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -256,6 +256,11 @@ Event::~Event() { videowriter = nullptr; } + // endtime is set in AddFrame, so SHOULD be set to the value of the last frame timestamp. + if ( ! end_time.tv_sec ) { + Warning("Empty endtime for event. Should not happen. Setting to now."); + gettimeofday(&end_time, nullptr); + } struct DeltaTimeval delta_time; DELTA_TIMEVAL(delta_time, end_time, start_time, DT_PREC_2); Debug(2, "start_time:%d.%d end_time%d.%d", start_time.tv_sec, start_time.tv_usec, end_time.tv_sec, end_time.tv_usec); @@ -569,6 +574,7 @@ void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, str } else { Debug(1, "No valid pre-capture frames to add"); } + end_time = *timestamps[n_frames-1]; } // void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, struct timeval **timestamps) void Event::WriteDbFrames() { From 432ae9894bfe91226c0d667b9e0940fac200966f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 Nov 2020 08:34:41 -0500 Subject: [PATCH 105/169] Add EndTime IS NOT NULL to PurgeWhenFull Filter --- db/zm_create.sql.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index d3e7af6b6..fa8f9d1f3 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -804,7 +804,7 @@ INSERT INTO `Filters` VALUES ( 'PurgeWhenFull', - '{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":100,"sort_asc":1}', + '{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="},{"cnj":"and","obr":"0","attr":"EndDateTime","op":"IS NOT","val":"NULL","cbr":"0"}],"limit":100,"sort_asc":1}', 0/*AutoArchive*/, 0/*AutoVideo*/, 0/*AutoUpload*/, From 903c6a2d5a31c27d1ff7594fb735b1797c3db371 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 Nov 2020 08:41:57 -0500 Subject: [PATCH 106/169] Add EndTime IS NOT NULL to UpdateDiskSpace Filter --- db/zm_create.sql.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index fa8f9d1f3..41ed75eba 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -848,7 +848,7 @@ INSERT INTO `Filters` ) VALUES ( 'Update DiskSpace', - '{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"}]}', + '{"terms":[{"attr":"DiskSpace","op":"IS","val":"NULL"},{"cnj":"and","obr":"0","attr":"EndDateTime","op":"IS NOT","val":"NULL","cbr":"0"}]}', 0/*AutoArchive*/, 0/*AutoVideo*/, 0/*AutoUpload*/, From f7c9a0e03d6a74749cc805b8890fe684b567bbf8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 Nov 2020 11:44:54 -0500 Subject: [PATCH 107/169] Must urlencode [Id]= --- web/includes/Filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Filter.php b/web/includes/Filter.php index bd22f3b89..068ee628e 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -60,7 +60,7 @@ class Filter extends ZM_Object { $this->_querystring .= $term->querystring($objectname, $separator); } # end foreach term if ( $this->Id() ) { - $this->_querystring .= $separator.$objectname.'[Id]='.$this->Id(); + $this->_querystring .= $separator.$objectname.urlencode('[Id]=').$this->Id(); } } return $this->_querystring; From dda1decfb1a3e80a238798afcd463e10e0f50277 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 Nov 2020 11:45:22 -0500 Subject: [PATCH 108/169] When redirecting after execute, redirect to the full filter querystring, as it may not have an Id and may have additional changes --- web/includes/actions/filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/actions/filter.php b/web/includes/actions/filter.php index 63f4af94e..572cccf08 100644 --- a/web/includes/actions/filter.php +++ b/web/includes/actions/filter.php @@ -95,7 +95,7 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) { } else if ( $filter->Background() ) { $filter->control('start'); } - $redirect = '?view=filter&Id='.$filter->Id(); + $redirect = '?view=filter'.$filter->querystring(); } else if ( $action == 'control' ) { if ( $_REQUEST['command'] == 'start' From b2385cceccf711659ac55eb991ef72b35373c669 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 Nov 2020 11:53:15 -0500 Subject: [PATCH 109/169] colour match a:link to navbar colour. This has the effect of brightening up all links. --- web/skins/classic/css/base/skin.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/css/base/skin.css b/web/skins/classic/css/base/skin.css index c6723b3a8..ee7a8a471 100644 --- a/web/skins/classic/css/base/skin.css +++ b/web/skins/classic/css/base/skin.css @@ -123,7 +123,7 @@ table th:last-child{ a:link { - color: #3498db; + color: #0fbcf9; text-decoration: none; } From 6112db627cfd469b7a4565db47ba390ba501b80f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 Nov 2020 11:59:28 -0500 Subject: [PATCH 110/169] Even if we found the filter in the db, if it is present in the query string, update the object with the new values --- web/skins/classic/views/filter.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index d53fff02a..bcf46e360 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -53,17 +53,17 @@ foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) { $filter = $Filter; } } -if ( !$filter ) { +if ( !$filter ) { $filter = new ZM\Filter(); - - if ( isset($_REQUEST['filter']) ) { - # Update our filter object with whatever changes we have made before saving - $filter->set($_REQUEST['filter']); - } -} else { - ZM\Debug('filter: ' . print_r($filter,true)); } +if ( isset($_REQUEST['filter']) ) { + # Update our filter object with whatever changes we have made before saving + $filter->set($_REQUEST['filter']); + ZM\Debug("Setting filter from " . print_r($_REQUEST['filter'], true)); +} +ZM\Debug('filter: ' . print_r($filter,true)); + $conjunctionTypes = ZM\getFilterQueryConjunctionTypes(); $obracketTypes = array(); $cbracketTypes = array(); From c72ceffe3d66011f1a12d3f6c80e7e35e76a0d8f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 Nov 2020 12:30:27 -0500 Subject: [PATCH 111/169] Improved testing for existence of foreign keys, better descriptive output of steps. --- db/zm_update-1.35.11.sql | 45 ++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/db/zm_update-1.35.11.sql b/db/zm_update-1.35.11.sql index ad73b7bf4..5e4338d76 100644 --- a/db/zm_update-1.35.11.sql +++ b/db/zm_update-1.35.11.sql @@ -1,7 +1,7 @@ /* Change Id type to BIGINT. */ set @exist := (SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'Events' AND COLUMN_NAME = 'Id' and DATA_TYPE='bigint'); -set @sqlstmt := if( @exist = 0, "ALTER TABLE Events MODIFY Id bigint unsigned NOT NULL auto_increment", "SELECT 'Ok'"); +set @sqlstmt := if( @exist = 0, "ALTER TABLE Events MODIFY Id bigint unsigned NOT NULL auto_increment", "SELECT 'Events.Id is already BIGINT'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; @@ -14,69 +14,78 @@ set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for EventId to Frame PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist != 0, "SELECT '.'", "SELECT 'Deleting unlinked Frames'"); +set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Frames'", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist != 0, "SELECT '.'", "DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events)"); +set @sqlstmt := if( @exist = 0, "DELETE FROM Frames WHERE EventId NOT IN (SELECT Id FROM Events)", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist != 0, "SELECT 'Ok'", "ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE"); +set @sqlstmt := if( @exist = 0, "ALTER TABLE Frames ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -SELECT 'Adding foreign key for EventId to Stats'; set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='EventId' and referenced_table_name='Events' and referenced_column_name='Id'); set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); -set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY already EventId in Stats already exists'", @sqlstmt); +set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY EventId in Stats already exists'", @sqlstmt); set @sqlstmt := if( @exist = 0, "SELECT 'Adding FOREIGN KEY for EventId to Stats'", @sqlstmt); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for EventId in Stats already exists'", "DELETE FROM Stats WHERE EventId NOT IN (SELECT Id FROM Events);"); +set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Stats'", "SELECT '.'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; +set @sqlstmt := if( @exist = 0, "DELETE FROM Stats WHERE EventId NOT IN (SELECT Id FROM Events);", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Stats ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE"); +set @sqlstmt := if( @exist = 0, "ALTER TABLE Stats ADD FOREIGN KEY (EventId) REFERENCES Events (Id) ON DELETE CASCADE", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -SELECT 'Adding foreign key for MonitorId to Stats'; set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='MonitorId' and referenced_table_name='Monitors' and referenced_column_name='Id'); set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY for MonitorId in Stats already exists'", @sql_stmt); +set @sqlstmt := if( @exist = 0, "SELECT 'Adding FOREIGN KEY for MonitorId to Stats'", @sqlstmt); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for MonitorId in Stats already exists'", "DELETE FROM Stats WHERE MonitorId NOT IN (SELECT Id FROM Monitors);"); +set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Stats'", "SELECT '.'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; +set @sqlstmt := if( @exist = 0, "DELETE FROM Stats WHERE MonitorId NOT IN (SELECT Id FROM Monitors);", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Stats ADD FOREIGN KEY (MonitorId) REFERENCES Monitors (Id) ON DELETE CASCADE"); +set @sqlstmt := if( @exist = 0, "ALTER TABLE Stats ADD FOREIGN KEY (MonitorId) REFERENCES Monitors (Id) ON DELETE CASCADE", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -SELECT 'Adding foreign key for ZoneId to Stats'; set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Stats' and column_name='ZoneId' and referenced_table_name='Zones' and referenced_column_name='Id'); set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); +set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY for ZoneId in Stats already exists'", @sqlstmt); +set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for ZoneId to Stats'", @sqlstmt); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; -set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for ZoneId in Stats already exists'", "DELETE FROM Stats WHERE ZoneId NOT IN (SELECT Id FROM Zones);"); +set @sqlstmt := if( @exist = 0, "SELECT 'Deleting unlinked Stats'", "SELECT 'Ok'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; - -set @sqlstmt := if( @exist > 0, "SELECT 'Ok'", "ALTER TABLE Stats ADD FOREIGN KEY (ZoneId) REFERENCES Zones (Id) ON DELETE CASCADE"); +set @sqlstmt := if( @exist = 0, "DELETE FROM Stats WHERE ZoneId NOT IN (SELECT Id FROM Zones);", "SELECT '.'"); +PREPARE stmt FROM @sqlstmt; +EXECUTE stmt; +set @sqlstmt := if( @exist = 0, "ALTER TABLE Stats ADD FOREIGN KEY (ZoneId) REFERENCES Zones (Id) ON DELETE CASCADE", "SELECT '.'"); PREPARE stmt FROM @sqlstmt; EXECUTE stmt; SELECT 'Adding foreign key for MonitorId to Zones'; set @exist := (select count(*) FROM information_schema.key_column_usage where table_name='Zones' and column_name='MonitorId' and referenced_table_name='Monitors' and referenced_column_name='Id'); set @sqlstmt := if( @exist > 1, "SELECT 'You have more than 1 FOREIGN KEY. Please do manual cleanup'", "SELECT 'Ok'"); -PREPARE stmt FROM @sqlstmt; -EXECUTE stmt; +set @sqlstmt := if( @exist = 1, "SELECT 'FOREIGN KEY for MonitorId in Zones already exists'", @sqlstmnt); +set @sqlstmt := if( @exist = 0, "SELECT 'Adding foreign key for MonitorId in Zones'", @sqlstmnt); -set @sqlstmt := if( @exist > 0, "SELECT 'FOREIGN KEY for MonitorId in Zones already exists'", "SELECT 'FOREIGN KEY for MonitorId in Zones does not already exist'"); +/*"SELECT 'FOREIGN KEY for MonitorId in Zones does not already exist'");*/ set @badzones := (select count(*) FROM Zones WHERE MonitorId NOT IN (SELECT Id FROM Monitors)); set @sqlstmt := if ( @badzones > 0, "SELECT 'You have Zones with no Monitor record in the Monitors table. Please delete them manually'", "ALTER TABLE Zones ADD FOREIGN KEY (MonitorId) REFERENCES Monitors (Id)"); PREPARE stmt FROM @sqlstmt; From af399bb1748a184ceec36c354a6973a5fcc94b6f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 09:18:41 -0500 Subject: [PATCH 112/169] Reqiure Id to have a value not just be set --- web/skins/classic/views/filter.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index bcf46e360..1ce614795 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -35,13 +35,12 @@ $filterNames = array(''=>translate('ChooseFilter')); $filter = NULL; $fid = 0; -if ( isset($_REQUEST['Id']) ) { +if ( isset($_REQUEST['Id']) and $_REQUEST['Id'] ) { $fid = validInt($_REQUEST['Id']); } else if ( isset($_REQUEST['filter[Id]']) ) { $fid = validInt($_REQUEST['filter[Id]']); - ZM\Warning("got fid by object id $fid"); } - +$filter = null; foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) { $filterNames[$Filter->Id()] = $Filter->Id() . ' ' . $Filter->Name(); if ( $Filter->Background() ) From 09fe354a22e8a64c31b2b3aa4b4b57c38acdda96 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 11:59:08 -0500 Subject: [PATCH 113/169] If event db insert fails, try again until it succeeds. --- src/zm_event.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index e762698fa..e48cb701e 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -106,12 +106,10 @@ Event::Event( storage->SchemeString().c_str() ); db_mutex.lock(); - if ( mysql_query(&dbconn, sql) ) { + while ( mysql_query(&dbconn, sql) ) { db_mutex.unlock(); Error("Can't insert event: %s. sql was (%s)", mysql_error(&dbconn), sql); - return; - } else { - Debug(2, "Created new event with %s", sql); + db_mutex.lock(); } id = mysql_insert_id(&dbconn); From 387b2b1fc20545149dfe27591427fc04fcb34e6d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 12:39:42 -0500 Subject: [PATCH 114/169] add attr validation to addTerm. Add addTerms --- web/includes/Filter.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/web/includes/Filter.php b/web/includes/Filter.php index 068ee628e..20a04c229 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -1,6 +1,7 @@ terms(); if ( (!isset($position)) or ($position > count($terms)) ) @@ -650,5 +656,12 @@ class Filter extends ZM_Object { return $this; } # end function addTerm + function addTerms($terms, $options=null) { + foreach ( $terms as $term ) { + $this->addTerm($term); + } + return $this; + } + } # end class Filter ?> From e67532ef76ac4d37c29f14ef62faa12e1e5b94ac Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 12:40:43 -0500 Subject: [PATCH 115/169] implement is_valid_attr. Fix incorrect EventDiskspace vs FS DiskSpace. FS DiskSpace isn't implemented. DiskPercent is. --- web/includes/FilterTerm.php | 67 +++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/web/includes/FilterTerm.php b/web/includes/FilterTerm.php index 4b2b1b78e..ebae24bb5 100644 --- a/web/includes/FilterTerm.php +++ b/web/includes/FilterTerm.php @@ -13,6 +13,7 @@ function getFilterQueryConjunctionTypes() { return $validConjunctionTypes; } + class FilterTerm { public $filter; public $index; @@ -35,7 +36,7 @@ class FilterTerm { $this->val = $term['val']; if ( isset($term['cnj']) ) { if ( array_key_exists($term['cnj'], $validConjunctionTypes) ) { - $this->cnj = $term['cnj']; + $this->cnj = $term['cnj']; } else { Warning('Invalid cnj ' . $term['cnj'].' in '.print_r($term, true)); } @@ -65,7 +66,8 @@ class FilterTerm { return $values; } - foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $this->val)) as $value ) { + $vals = is_array($this->val) ? $this->val : preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $this->val)); + foreach ( $vals as $value ) { switch ( $this->attr ) { @@ -75,7 +77,7 @@ class FilterTerm { case 'ExistsInFileSystem': $value = ''; break; - case 'DiskSpace': + case 'DiskPercent': $value = ''; break; case 'MonitorName': @@ -83,7 +85,7 @@ class FilterTerm { case 'Name': case 'Cause': case 'Notes': - if ( $this->op == 'LIKE' || $this->op == 'NOT LIKE' ) { + if ( strstr($this->op, 'LIKE') and ! strstr($this->val, '%' ) ) { $value = '%'.$value.'%'; } $value = dbEscape($value); @@ -145,7 +147,7 @@ class FilterTerm { case 'AlarmZoneId': return ' EXISTS '; case 'ExistsInFileSystem': - case 'DiskSpace': + case 'DiskPercent': return ''; } @@ -202,7 +204,7 @@ class FilterTerm { switch ( $this->attr ) { case 'ExistsInFileSystem': - case 'DiskSpace': + case 'DiskPercent': $sql .= 'TRUE /*'.$this->attr.'*/'; break; case 'MonitorName': @@ -260,9 +262,10 @@ class FilterTerm { case 'EndWeekday': $sql .= 'weekday(E.EndTime)'; break; + case 'Emailed': case 'Id': case 'Name': - case 'EventDiskSpace': + case 'DiskSpace': case 'MonitorId': case 'StorageId': case 'SecondaryStorageId': @@ -400,21 +403,63 @@ class FilterTerm { } public function is_pre_sql() { - if ( $this->attr == 'DiskPercent' ) { + if ( $this->attr == 'DiskPercent' ) + return true; + if ( $this->attr == 'DiskBlocks' ) return true; - } return false; } public function is_post_sql() { if ( $this->attr == 'ExistsInFileSystem' ) { return true; - } else if ( $this->attr == 'DiskPercent' ) { - return true; } return false; } + public static function is_valid_attr($attr) { + $attrs = array( + 'ExistsInFileSystem', + 'Emailed', + 'DiskSpace', + 'DiskPercent', + 'DiskBlocks', + 'MonitorName', + 'ServerId', + 'MonitorServerId', + 'StorageServerId', + 'FilterServerId', + 'DateTime', + 'Date', + 'Time', + 'Weekday', + 'StartDateTime', + '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 ?> From 4731041a40d56905c532a51e92efc15f09fa86f2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 12:42:04 -0500 Subject: [PATCH 116/169] FS Storage DiskSpace isn't implemented. --- web/skins/classic/views/filter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 1ce614795..fe90681b3 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -88,8 +88,8 @@ $attrTypes = array( 'Cause' => translate('AttrCause'), 'DiskBlocks' => translate('AttrDiskBlocks'), 'DiskPercent' => translate('AttrDiskPercent'), - 'DiskSpace' => translate('AttrDiskSpace'), - 'EventDiskSpace' => translate('AttrEventDiskSpace'), + #'StorageDiskSpace' => translate('AttrStorageDiskSpace'), + 'DiskSpace' => translate('AttrEventDiskSpace'), 'EndDateTime' => translate('AttrEndDateTime'), 'EndDate' => translate('AttrEndDate'), 'EndTime' => translate('AttrEndTime'), From adbd3486bfa26a58c5190ed7dcd9e3601aa3b730 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:49:39 -0500 Subject: [PATCH 117/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- db/triggers.sql | 12 +++---- db/zm_create.sql.in | 24 ++++++------- scripts/ZoneMinder/lib/ZoneMinder/Event.pm | 26 +++++++------- scripts/ZoneMinder/lib/ZoneMinder/Filter.pm | 36 ++++++++++--------- scripts/ZoneMinder/lib/ZoneMinder/General.pm | 16 ++++----- scripts/zmaudit.pl.in | 38 ++++++++++---------- scripts/zmfilter.pl.in | 2 +- scripts/zmrecover.pl.in | 14 ++++---- scripts/zmstats.pl.in | 8 ++--- scripts/zmvideo.pl.in | 2 +- 10 files changed, 90 insertions(+), 88 deletions(-) diff --git a/db/triggers.sql b/db/triggers.sql index 87c8465b4..ad697be54 100644 --- a/db/triggers.sql +++ b/db/triggers.sql @@ -152,13 +152,13 @@ BEGIN SET ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0), ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitors.Id=OLD.MonitorId; ELSE IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; UPDATE Monitors SET ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitors.Id=OLD.MonitorId; END IF; END IF; ELSEIF ( NEW.Archived AND diff ) THEN @@ -185,10 +185,10 @@ CREATE TRIGGER event_insert_trigger AFTER INSERT ON Events FOR EACH ROW BEGIN - INSERT INTO Events_Hour (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); - INSERT INTO Events_Day (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); - INSERT INTO Events_Week (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); - INSERT INTO Events_Month (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Hour (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Day (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Week (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Month (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); UPDATE Monitors SET HourEvents = COALESCE(HourEvents,0)+1, DayEvents = COALESCE(DayEvents,0)+1, diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 41ed75eba..40063a74c 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -189,8 +189,8 @@ CREATE TABLE `Events` ( `SecondaryStorageId` smallint(5) unsigned default 0, `Name` varchar(64) NOT NULL default '', `Cause` varchar(32) NOT NULL default '', - `StartTime` datetime default NULL, - `EndTime` datetime default NULL, + `StartDateTime` datetime default NULL, + `EndDateTime` datetime default NULL, `Width` smallint(5) unsigned NOT NULL default '0', `Height` smallint(5) unsigned NOT NULL default '0', `Length` decimal(10,2) NOT NULL default '0.00', @@ -216,52 +216,52 @@ CREATE TABLE `Events` ( PRIMARY KEY (`Id`), KEY `Events_MonitorId_idx` (`MonitorId`), KEY `Events_StorageId_idx` (`StorageId`), - KEY `Events_StartTime_idx` (`StartTime`), - KEY `Events_EndTime_DiskSpace` (`EndTime`,`DiskSpace`) + KEY `Events_StartDateTime_idx` (`StartDateTime`), + KEY `Events_EndDateTime_DiskSpace` (`EndDateTime`,`DiskSpace`) ) ENGINE=@ZM_MYSQL_ENGINE@; DROP TABLE IF EXISTS `Events_Hour`; CREATE TABLE `Events_Hour` ( `EventId` BIGINT unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL, - `StartTime` datetime default NULL, + `StartDateTime` datetime default NULL, `DiskSpace` bigint default NULL, PRIMARY KEY (`EventId`), KEY `Events_Hour_MonitorId_idx` (`MonitorId`), - KEY `Events_Hour_StartTime_idx` (`StartTime`) + KEY `Events_Hour_StartDateTime_idx` (`StartDateTime`) ) ENGINE=@ZM_MYSQL_ENGINE@; DROP TABLE IF EXISTS `Events_Day`; CREATE TABLE `Events_Day` ( `EventId` BIGINT unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL, - `StartTime` datetime default NULL, + `StartDateTime` datetime default NULL, `DiskSpace` bigint default NULL, PRIMARY KEY (`EventId`), KEY `Events_Day_MonitorId_idx` (`MonitorId`), - KEY `Events_Day_StartTime_idx` (`StartTime`) + KEY `Events_Day_StartDateTime_idx` (`StartDateTime`) ) ENGINE=@ZM_MYSQL_ENGINE@; DROP TABLE IF EXISTS `Events_Week`; CREATE TABLE `Events_Week` ( `EventId` BIGINT unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL, - `StartTime` datetime default NULL, + `StartDateTime` datetime default NULL, `DiskSpace` bigint default NULL, PRIMARY KEY (`EventId`), KEY `Events_Week_MonitorId_idx` (`MonitorId`), - KEY `Events_Week_StartTime_idx` (`StartTime`) + KEY `Events_Week_StartDateTime_idx` (`StartDateTime`) ) ENGINE=@ZM_MYSQL_ENGINE@; DROP TABLE IF EXISTS `Events_Month`; CREATE TABLE `Events_Month` ( `EventId` BIGINT unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL, - `StartTime` datetime default NULL, + `StartDateTime` datetime default NULL, `DiskSpace` bigint default NULL, PRIMARY KEY (`EventId`), KEY `Events_Month_MonitorId_idx` (`MonitorId`), - KEY `Events_Month_StartTime_idx` (`StartTime`) + KEY `Events_Month_StartDateTime_idx` (`StartDateTime`) ) ENGINE=@ZM_MYSQL_ENGINE@; diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 985ac71f3..2664830dd 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -68,8 +68,8 @@ $serial = $primary_key = 'Id'; SecondaryStorageId Name Cause - StartTime - EndTime + StartDateTime + EndDateTime Width Height Length @@ -111,8 +111,8 @@ sub Time { $_[0]{Time} = $_[1]; } if ( ! defined $_[0]{Time} ) { - if ( $_[0]{StartTime} ) { - $_[0]{Time} = Date::Parse::str2time( $_[0]{StartTime} ); + if ( $_[0]{StartDateTime} ) { + $_[0]{Time} = Date::Parse::str2time( $_[0]{StartDateTime} ); } } return $_[0]{Time}; @@ -364,11 +364,11 @@ sub delete { my $in_zmaudit = ( $0 =~ 'zmaudit.pl$'); if ( ! $in_zmaudit ) { - if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartTime} ) ) { + if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartDateTime} ) ) { # zmfilter shouldn't delete anything in an odd situation. zmaudit will though. my ( $caller, undef, $line ) = caller; - Warning("$0 Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartTime:". - (defined($event->{StartTime})?$event->{StartTime}:'undef')." from $caller:$line"); + Warning("$0 Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartDateTime:". + (defined($event->{StartDateTime})?$event->{StartDateTime}:'undef')." from $caller:$line"); return; } if ( !($event->Storage()->Path() and -e $event->Storage()->Path()) ) { @@ -379,7 +379,7 @@ sub delete { if ( $$event{Id} ) { # Need to have an event Id if we are to delete from the db. - Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime} from ".$event->Path()); + Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartDateTime:$event->{StartDateTime} from ".$event->Path()); $ZoneMinder::Database::dbh->ping(); my $in_transaction = $ZoneMinder::Database::dbh->{AutoCommit} ? 0 : 1; @@ -820,9 +820,9 @@ sub recover_timestamps { my $duration = $last_timestamp - $first_timestamp; $Event->Length($duration); - $Event->StartTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) ); - $Event->EndTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $last_timestamp) ); - Debug("From capture Jpegs have duration $duration = $last_timestamp - $first_timestamp : $$Event{StartTime} to $$Event{EndTime}"); + $Event->StartDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) ); + $Event->EndDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $last_timestamp) ); + Debug("From capture Jpegs have duration $duration = $last_timestamp - $first_timestamp : $$Event{StartDateTime} to $$Event{EndDateTime}"); $ZoneMinder::Database::dbh->begin_work(); foreach my $jpg ( @capture_jpgs ) { my ( $id ) = $jpg =~ /^(\d+)\-capture\.jpg$/; @@ -858,8 +858,8 @@ sub recover_timestamps { } my $seconds = ($h*60*60)+($m*60)+$s; $Event->Length($seconds.'.'.$u); - $Event->StartTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) ); - $Event->EndTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp+$seconds) ); + $Event->StartDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp) ); + $Event->EndDateTime( Date::Format::time2str('%Y-%m-%d %H:%M:%S', $first_timestamp+$seconds) ); } if ( @mp4_files ) { $Event->DefaultVideo($mp4_files[0]); diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm index 85c09b141..eb1b36077 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm @@ -149,7 +149,7 @@ sub Sql { my $filter_expr = ZoneMinder::General::jsonDecode($self->{Query_json}); my $sql = 'SELECT E.*, - unix_timestamp(E.StartTime) as Time, + unix_timestamp(E.StartDateTime) as Time, M.Name as MonitorName, M.DefaultRate, M.DefaultScale @@ -184,27 +184,25 @@ sub Sql { $self->{Sql} .= $Config{ZM_SERVER_ID}; # StartTime options } elsif ( $term->{attr} eq 'DateTime' ) { - $self->{Sql} .= 'E.StartTime'; - } elsif ( $term->{attr} eq 'StartDateTime' ) { - $self->{Sql} .= 'E.StartTime'; + $self->{Sql} .= 'E.StartDateTime'; } elsif ( $term->{attr} eq 'Date' ) { - $self->{Sql} .= 'to_days( E.StartTime )'; + $self->{Sql} .= 'to_days( E.StartDateTime )'; } elsif ( $term->{attr} eq 'StartDate' ) { - $self->{Sql} .= 'to_days( E.StartTime )'; + $self->{Sql} .= 'to_days( E.StartDateTime )'; } elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' ) { - $self->{Sql} .= 'extract( hour_second from E.StartTime )'; + $self->{Sql} .= 'extract( hour_second from E.StartDateTime )'; } elsif ( $term->{attr} eq 'Weekday' or $term->{attr} eq 'StartWeekday' ) { - $self->{Sql} .= 'weekday( E.StartTime )'; + $self->{Sql} .= 'weekday( E.StartDateTime )'; # EndTIme options } elsif ( $term->{attr} eq 'EndDateTime' ) { - $self->{Sql} .= 'E.EndTime'; + $self->{Sql} .= 'E.EndDateTime'; } elsif ( $term->{attr} eq 'EndDate' ) { - $self->{Sql} .= 'to_days( E.EndTime )'; - } elsif ( $term->{attr} eq 'EndTime' ) { - $self->{Sql} .= 'extract( hour_second from E.EndTime )'; + $self->{Sql} .= 'to_days( E.EndDateTime )'; + } elsif ( $term->{attr} eq 'EndDateTime' ) { + $self->{Sql} .= 'extract( hour_second from E.EndDateTime )'; } elsif ( $term->{attr} eq 'EndWeekday' ) { - $self->{Sql} .= "weekday( E.EndTime )"; + $self->{Sql} .= "weekday( E.EndDateTime )"; } elsif ( $term->{attr} eq 'ExistsInFileSystem' ) { push @{$self->{PostSQLConditions}}, $term; $self->{Sql} .= 'TRUE /* ExistsInFileSystem */'; @@ -368,7 +366,7 @@ sub Sql { $sql .= ' AND ( '.join(' or ', @auto_terms).' )'; } if ( !$filter_expr->{sort_field} ) { - $filter_expr->{sort_field} = 'StartTime'; + $filter_expr->{sort_field} = 'StartDateTime'; $filter_expr->{sort_asc} = 0; } my $sort_column = ''; @@ -378,10 +376,14 @@ sub Sql { $sort_column = 'M.Name'; } elsif ( $filter_expr->{sort_field} eq 'Name' ) { $sort_column = 'E.Name'; + } elsif ( $filter_expr->{sort_field} eq 'StartDateTime' ) { + $sort_column = 'E.StartDateTime'; } elsif ( $filter_expr->{sort_field} eq 'StartTime' ) { - $sort_column = 'E.StartTime'; + $sort_column = 'E.StartDateTime'; } elsif ( $filter_expr->{sort_field} eq 'EndTime' ) { - $sort_column = 'E.EndTime'; + $sort_column = 'E.EndDateTime'; + } elsif ( $filter_expr->{sort_field} eq 'EndDateTime' ) { + $sort_column = 'E.EndDateTime'; } elsif ( $filter_expr->{sort_field} eq 'Secs' ) { $sort_column = 'E.Length'; } elsif ( $filter_expr->{sort_field} eq 'Frames' ) { @@ -397,7 +399,7 @@ sub Sql { } elsif ( $filter_expr->{sort_field} eq 'DiskSpace' ) { $sort_column = 'E.DiskSpace'; } else { - $sort_column = 'E.StartTime'; + $sort_column = 'E.StartDateTime'; } my $sort_order = $filter_expr->{sort_asc} ? 'ASC' : 'DESC'; $sql .= ' ORDER BY '.$sort_column.' '.$sort_order; diff --git a/scripts/ZoneMinder/lib/ZoneMinder/General.pm b/scripts/ZoneMinder/lib/ZoneMinder/General.pm index 0d3784185..d68967fa9 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/General.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/General.pm @@ -262,21 +262,21 @@ sub createEvent { } $frame->{Type} = $frame->{Score}>0?'Alarm':'Normal' unless( $frame->{Type} ); $frame->{Delta} = $lastTimestamp?($frame->{TimeStamp}-$lastTimestamp):0.0; - $event->{StartTime} = $frame->{TimeStamp} unless ( $event->{StartTime} ); + $event->{StartDateTime} = $frame->{TimeStamp} unless ( $event->{StartDateTime} ); $event->{TotScore} += $frame->{Score}; $event->{MaxScore} = $frame->{Score} if ( $frame->{Score} > $event->{MaxScore} ); $event->{AlarmFrames}++ if ( $frame->{Type} eq 'Alarm' ); - $event->{EndTime} = $frame->{TimeStamp}; + $event->{EndDateTime} = $frame->{TimeStamp}; $lastTimestamp = $frame->{TimeStamp}; } $event->{Width} = $event->{monitor}->{Width} unless( $event->{Width} ); $event->{Height} = $event->{monitor}->{Height} unless( $event->{Height} ); $event->{AvgScore} = $event->{TotScore}/int($event->{AlarmFrames}); - $event->{Length} = $event->{EndTime} - $event->{StartTime}; + $event->{Length} = $event->{EndDateTime} - $event->{StartDateTime}; my %formats = ( - StartTime => 'from_unixtime(?)', - EndTime => 'from_unixtime(?)', + StartDateTime => 'from_unixtime(?)', + EndDateTime => 'from_unixtime(?)', ); my ( @fields, @formats, @values ); @@ -297,7 +297,7 @@ sub createEvent { $event->{Id} = $dbh->{mysql_insertid}; Info( "Created event ".$event->{Id} ); - if ( $event->{EndTime} ) { + if ( $event->{EndDateTime} ) { $event->{Name} = $event->{monitor}->{EventPrefix}.$event->{Id} if ( $event->{Name} eq 'New Event' ); my $sql = "update Events set Name = ? where Id = ?"; @@ -383,8 +383,8 @@ sub updateEvent { if ( $event->{Name} eq 'New Event' ); my %formats = ( - StartTime => 'from_unixtime(?)', - EndTime => 'from_unixtime(?)', + StartDateTime => 'from_unixtime(?)', + EndDateTime => 'from_unixtime(?)', ); my ( @values, @sets ); diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index 80a227e2b..4601ea1aa 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -205,7 +205,7 @@ MAIN: while( $loop ) { my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql ) or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() ); - my $eventSelectSql = 'SELECT `Id`, (unix_timestamp() - unix_timestamp(`StartTime`)) AS Age + my $eventSelectSql = 'SELECT `Id`, (unix_timestamp() - unix_timestamp(`StartDateTime`)) AS Age FROM `Events` WHERE `MonitorId` = ?'.(@Storage_Areas ? ' AND `StorageId` IN ('.join(',',map { '?'} @Storage_Areas).')' : '' ). ' ORDER BY `Id`'; my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql ) or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() ); @@ -397,13 +397,13 @@ MAIN: while( $loop ) { my ( undef, $year, $month, $day ) = split('/', $day_dir); $year += 2000; my ( $hour, $minute, $second ) = split('/', $event_dir); - my $StartTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second); + my $StartDateTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second); my $Event = ZoneMinder::Event->find_one( MonitorId=>$monitor_dir, - StartTime=>$StartTime, + StartDateTime=>$StartDateTime, ); if ( $Event ) { - Debug("Found event matching starttime on monitor $monitor_dir at $StartTime: " . $Event->to_string()); + Debug("Found event matching StartDateTime on monitor $monitor_dir at $StartDateTime: " . $Event->to_string()); next; } aud_print("Deleting event directories with no event id information at $day_dir/$event_dir"); @@ -440,7 +440,7 @@ MAIN: while( $loop ) { $Event->Path(); $Event->age(); Debug("Have event $$Event{Id} at $$Event{Path}"); - $Event->StartTime(POSIX::strftime('%Y-%m-%d %H:%M:%S', gmtime(time_of_youngest_file($Event->Path())))); + $Event->StartDateTime(POSIX::strftime('%Y-%m-%d %H:%M:%S', gmtime(time_of_youngest_file($Event->Path())))); } # end foreach event } @@ -592,7 +592,7 @@ EVENT: while ( my ( $db_event, $age ) = each( %$db_events ) ) { Warning("Event $$Event{Id} is Archived. Taking no further action on it."); next; } - if ( !$Event->StartTime() ) { + if ( !$Event->StartDateTime() ) { aud_print("Event $$Event{Id} has no start time."); if ( confirm() ) { $Event->delete(); @@ -600,7 +600,7 @@ EVENT: while ( my ( $db_event, $age ) = each( %$db_events ) ) { } next; } - if ( ! $Event->EndTime() ) { + if ( ! $Event->EndDateTime() ) { if ( $age > $Config{ZM_AUDIT_MIN_AGE} ) { aud_print("Event $$Event{Id} has no end time and is $age seconds old. Deleting it."); if ( confirm() ) { @@ -639,9 +639,9 @@ EVENT: while ( my ( $db_event, $age ) = each( %$db_events ) ) { Info("Updating storage area on event $$Event{Id} from $$Event{StorageId} to $$fs_events{$db_event}{StorageId}"); $Event->StorageId($$fs_events{$db_event}->StorageId()); } - if ( ! $Event->StartTime() ) { - Info("Updating StartTime on event $$Event{Id} from $$Event{StartTime} to $$fs_events{$db_event}{StartTime}"); - $Event->StartTime($$fs_events{$db_event}->StartTime()); + if ( ! $Event->StartDateTime() ) { + Info("Updating StartDateTime on event $$Event{Id} from $$Event{StartDateTime} to $$fs_events{$db_event}{StartDateTime}"); + $Event->StartDateTime($$fs_events{$db_event}->StartDateTime()); } $Event->save(); @@ -683,12 +683,12 @@ if ( $level > 1 ) { # Remove empty events (with no frames) $cleaned = 0; Debug("Checking for Events with no Frames"); - my $selectEmptyEventsSql = 'SELECT `E`.`Id` AS `Id`, `E`.`StartTime`, `F`.`EventId` FROM `Events` AS E LEFT JOIN `Frames` AS F ON (`E`.`Id` = `F`.`EventId`) - WHERE isnull(`F`.`EventId`) AND now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second > `E`.`StartTime`'; + my $selectEmptyEventsSql = 'SELECT `E`.`Id` AS `Id`, `E`.`StartDateTime`, `F`.`EventId` FROM `Events` AS E LEFT JOIN `Frames` AS F ON (`E`.`Id` = `F`.`EventId`) + WHERE isnull(`F`.`EventId`) AND now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second > `E`.`StartDateTime`'; if ( my $selectEmptyEventsSth = $dbh->prepare_cached( $selectEmptyEventsSql ) ) { if ( $res = $selectEmptyEventsSth->execute() ) { while( my $event = $selectEmptyEventsSth->fetchrow_hashref() ) { - aud_print("Found empty event with no frame records '$event->{Id}' at $$event{StartTime}"); + aud_print("Found empty event with no frame records '$event->{Id}' at $$event{StartDateTime}"); if ( confirm() ) { if ( $res = $deleteEventSth->execute($event->{Id}) ) { $cleaned = 1; @@ -750,7 +750,7 @@ if ( $level > 1 ) { #"SELECT E.Id, ANY_VALUE(E.MonitorId), # #max(F.TimeStamp) as EndTime, -#unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length, +#unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartDateTime) as Length, #max(F.FrameId) as Frames, #count(if(F.Score>0,1,NULL)) as AlarmFrames, #sum(F.Score) as TotScore, @@ -760,11 +760,11 @@ if ( $level > 1 ) { #WHERE isnull(E.Frames) or isnull(E.EndTime) #GROUP BY E.Id HAVING EndTime < (now() - interval ".$Config{ZM_AUDIT_MIN_AGE}.' second)' #; - 'SELECT *, unix_timestamp(`StartTime`) AS `TimeStamp` FROM `Events` WHERE `EndTime` IS NULL AND `StartTime` < (now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second)'.($monitor_id?' AND MonitorId=?':''); + 'SELECT *, unix_timestamp(`StartDateTime`) AS `TimeStamp` FROM `Events` WHERE `EndDateTime` IS NULL AND `StartDateTime` < (now() - interval '.$Config{ZM_AUDIT_MIN_AGE}.' second)'.($monitor_id?' AND MonitorId=?':''); my $selectFrameDataSql = ' SELECT - max(`TimeStamp`) AS `EndTime`, + max(`TimeStamp`) AS `EndDateTime`, unix_timestamp(max(`TimeStamp`)) AS `EndTimeStamp`, max(`FrameId`) AS `Frames`, count(if(`Score`>0,1,NULL)) AS `AlarmFrames`, @@ -779,7 +779,7 @@ FROM `Frames` WHERE `EventId`=?'; my $updateUnclosedEventsSql = "UPDATE low_priority `Events` SET `Name` = ?, - `EndTime` = ?, + `EndDateTime` = ?, `Length` = ?, `Frames` = ?, `AlarmFrames` = ?, @@ -794,7 +794,7 @@ FROM `Frames` WHERE `EventId`=?'; $res = $selectUnclosedEventsSth->execute($monitor_id?$monitor_id:()) or Fatal("Can't execute: ".$selectUnclosedEventsSth->errstr()); while( my $event = $selectUnclosedEventsSth->fetchrow_hashref() ) { - aud_print("Found open event '$event->{Id}' on Monitor $event->{MonitorId} at $$event{StartTime}"); + aud_print("Found open event '$event->{Id}' on Monitor $event->{MonitorId} at $$event{StartDateTime}"); if ( confirm('close', 'closing') ) { if ( ! ( $res = $selectFrameDataSth->execute($event->{Id}) ) ) { Error("Can't execute: $selectFrameDataSql:".$selectFrameDataSth->errstr()); @@ -808,7 +808,7 @@ FROM `Frames` WHERE `EventId`=?'; $event->{Id}, RECOVER_TAG ), - $frame->{EndTime}, + $frame->{EndDateTime}, $frame->{EndTimeStamp} - $event->{TimeStamp}, $frame->{Frames}, $frame->{AlarmFrames}, diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 5540e6944..834da99f8 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -704,7 +704,7 @@ sub substituteTags { $text =~ s/%EN%/$Event->{Name}/g; $text =~ s/%EC%/$Event->{Cause}/g; $text =~ s/%ED%/$Event->{Notes}/g; - $text =~ s/%ET%/$Event->{StartTime}/g; + $text =~ s/%ET%/$Event->{StartDateTime}/g; $text =~ s/%EVF%/$$Event{DefaultVideo}/g; # Event video filename $text =~ s/%EL%/$Event->{Length}/g; $text =~ s/%EF%/$Event->{Frames}/g; diff --git a/scripts/zmrecover.pl.in b/scripts/zmrecover.pl.in index 58647b946..c52537b4e 100644 --- a/scripts/zmrecover.pl.in +++ b/scripts/zmrecover.pl.in @@ -231,7 +231,7 @@ Debug("@Monitors"); $Event->Height( $Monitor->Height() ); $Event->Orientation( $Monitor->Orientation() ); $Event->recover_timestamps(); - if ( $$Event{StartTime} ) { + if ( $$Event{StartDateTime} ) { $Event->save({}, 1); Info("Event resurrected as " . $Event->to_string() ); } else { @@ -294,7 +294,7 @@ Debug("@Monitors"); $Event->StorageId( $Storage->Id() ); $Event->DiskSpace( undef ); $Event->recover_timestamps(); - if ( $$Event{StartTime} ) { + if ( $$Event{StartDateTime} ) { $Event->save({}, 1); Info("Event resurrected as " . $Event->to_string() ); } else { @@ -309,13 +309,13 @@ Debug("@Monitors"); my ( undef, $year, $month, $day ) = split('/', $day_dir); $year += 2000; my ( $hour, $minute, $second ) = split('/', $event_dir); - my $StartTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second); + my $StartDateTime =sprintf('%.4d-%.2d-%.2d %.2d:%.2d:%.2d', $year, $month, $day, $hour, $minute, $second); my $Event = ZoneMinder::Event->find_one( MonitorId=>$monitor_dir, - StartTime=>$StartTime, + StartDateTime=>$StartDateTime, ); if ( $Event ) { - Debug("Found event matching starttime on monitor $monitor_dir at $StartTime: " . $Event->to_string()); + Debug("Found event matching starttime on monitor $monitor_dir at $StartDateTime: " . $Event->to_string()); next; } @@ -358,7 +358,7 @@ Debug("@Monitors"); $Event->Orientation( $Monitor->Orientation() ); $Event->StorageId( $Storage->Id() ); $Event->recover_timestamps(); - if ( $$Event{StartTime} ) { + if ( $$Event{StartDateTime} ) { $Event->save({}, 1); Info("Event resurrected as " . $Event->to_string() ); } else { @@ -400,7 +400,7 @@ Debug("@Monitors"); $Event->Orientation( $Monitor->Orientation() ); $Event->StorageId( $Storage->Id() ); $Event->recover_timestamps(); - if ( $$Event{StartTime} ) { + if ( $$Event{StartDateTime} ) { $Event->save({}, 1); Info("Event resurrected as " . $Event->to_string() ); } else { diff --git a/scripts/zmstats.pl.in b/scripts/zmstats.pl.in index 555d9c602..8aef4ddc6 100644 --- a/scripts/zmstats.pl.in +++ b/scripts/zmstats.pl.in @@ -43,10 +43,10 @@ while( 1 ) { } } - $dbh->do('DELETE FROM Events_Hour WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 hour)') or Error($dbh->errstr()); - $dbh->do('DELETE FROM Events_Day WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 day)') or Error($dbh->errstr()); - $dbh->do('DELETE FROM Events_Week WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 week)') or Error($dbh->errstr()); - $dbh->do('DELETE FROM Events_Month WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 month)') or Error($dbh->errstr()); + $dbh->do('DELETE FROM Events_Hour WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 hour)') or Error($dbh->errstr()); + $dbh->do('DELETE FROM Events_Day WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 day)') or Error($dbh->errstr()); + $dbh->do('DELETE FROM Events_Week WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 week)') or Error($dbh->errstr()); + $dbh->do('DELETE FROM Events_Month WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 month)') or Error($dbh->errstr()); # Prune the Logs table if required if ( $Config{ZM_LOG_DATABASE_LIMIT} ) { diff --git a/scripts/zmvideo.pl.in b/scripts/zmvideo.pl.in index 04cfabb04..c676eb164 100644 --- a/scripts/zmvideo.pl.in +++ b/scripts/zmvideo.pl.in @@ -201,7 +201,7 @@ if ( $event_id ) { my $sql = " SELECT (SELECT max(Delta) FROM Frames WHERE EventId=Events.Id)-(SELECT min(Delta) FROM Frames WHERE EventId=Events.Id) as FullLength, Events.*, - unix_timestamp(Events.StartTime) as Time, + unix_timestamp(Events.StartDateTime) as Time, M.Name as MonitorName, M.Palette FROM Events From 33f58add118001bf6ad703845397f5c07448c15f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:49:47 -0500 Subject: [PATCH 118/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- src/zm_event.cpp | 8 ++++---- src/zm_eventstream.cpp | 6 +++--- src/zm_monitor.cpp | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index e48cb701e..cd7ba1918 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -71,7 +71,7 @@ Event::Event( start_time = now; } else if ( start_time.tv_sec > now.tv_sec ) { Error( - "StartTime in the future %u.%u > %u.%u", + "StartDateTime in the future %u.%u > %u.%u", start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec ); start_time = now; @@ -89,7 +89,7 @@ Event::Event( char sql[ZM_SQL_MED_BUFSIZ]; struct tm *stime = localtime(&start_time.tv_sec); snprintf(sql, sizeof(sql), "INSERT INTO Events " - "( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme )" + "( MonitorId, StorageId, Name, StartDateTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme )" " VALUES ( %u, %u, 'New Event', from_unixtime( %ld ), %u, %u, '%s', '%s', %u, %d, %d, '%s', %d, '%s' )", monitor->Id(), storage->Id(), @@ -289,7 +289,7 @@ Event::~Event() { // Should not be static because we might be multi-threaded char sql[ZM_SQL_LGE_BUFSIZ]; snprintf(sql, sizeof(sql), - "UPDATE Events SET Name='%s%" PRIu64 "', EndTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64 " AND Name='New Event'", + "UPDATE Events SET Name='%s%" PRIu64 "', EndDateTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64 " AND Name='New Event'", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, @@ -305,7 +305,7 @@ Event::~Event() { if ( !mysql_affected_rows(&dbconn) ) { // Name might have been changed during recording, so just do the update without changing the name. snprintf(sql, sizeof(sql), - "UPDATE Events SET EndTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64, + "UPDATE Events SET EndDateTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 6f2ba4197..2c8ec7c08 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -45,7 +45,7 @@ bool EventStream::loadInitialEventData(int monitor_id, time_t event_time) { static char sql[ZM_SQL_SML_BUFSIZ]; snprintf(sql, sizeof(sql), "SELECT `Id` FROM `Events` WHERE " - "`MonitorId` = %d AND unix_timestamp(`EndTime`) > %ld " + "`MonitorId` = %d AND unix_timestamp(`EndDateTime`) > %ld " "ORDER BY `Id` ASC LIMIT 1", monitor_id, event_time); if ( mysql_query(&dbconn, sql) ) { @@ -116,8 +116,8 @@ bool EventStream::loadEventData(uint64_t event_id) { static char sql[ZM_SQL_MED_BUFSIZ]; snprintf(sql, sizeof(sql), - "SELECT `MonitorId`, `StorageId`, `Frames`, unix_timestamp( `StartTime` ) AS StartTimestamp, " - "unix_timestamp( `EndTime` ) AS EndTimestamp, " + "SELECT `MonitorId`, `StorageId`, `Frames`, unix_timestamp( `StartDateTime` ) AS StartTimestamp, " + "unix_timestamp( `EndDateTime` ) AS EndTimestamp, " "(SELECT max(`Delta`)-min(`Delta`) FROM `Frames` WHERE `EventId`=`Events`.`Id`) AS Duration, " "`DefaultVideo`, `Scheme`, `SaveJPEGs`, `Orientation`+0 FROM `Events` WHERE `Id` = %" PRIu64, event_id); diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 231b02916..937a4bf3a 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1613,7 +1613,6 @@ bool Monitor::Analyse() { } // end if analysis_fps && pre_event_count shared_data->last_event = event->Id(); - //set up video store data snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile()); video_store_data->recording = event->StartTime(); From 0d404ac66f0db739dc8ee8e56877e5b122691783 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:50:45 -0500 Subject: [PATCH 119/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/events.php | 4 ++-- web/skins/classic/views/js/events.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index 555f13f51..86376d6b4 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -104,8 +104,8 @@ getBodyTopHTML(); - - + + diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 20bf6b87f..7d4c67369 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -17,14 +17,14 @@ var params = "data": { "search":"some search text", - "sort":"StartTime", + "sort":"StartDateTime", "order":"asc", "offset":0, "limit":25 "filter": { "Name":"some advanced search text" - "StartTime":"some more advanced search text" + "StartDateTime":"some more advanced search text" } }, "cache":true, From 2d33dd5386dca643b719d57e3f360278e2eb98a6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:52:32 -0500 Subject: [PATCH 120/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/includes/Event.php | 16 ++++++++-------- web/includes/Filter.php | 16 ++++++++-------- web/includes/FilterTerm.php | 24 ++++++++++++------------ 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/web/includes/Event.php b/web/includes/Event.php index 70eb27d8c..4e218edb2 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -14,8 +14,8 @@ class Event extends ZM_Object { 'StorageId' => null, 'SecondaryStorageId' => null, 'Cause' => '', - 'StartTime' => null, - 'EndTime' => null, + 'StartDateTime' => null, + 'EndDateTime' => null, 'Width' => null, 'Height' => null, 'Length' => null, @@ -93,7 +93,7 @@ class Event extends ZM_Object { public function Time() { if ( ! isset($this->{'Time'}) ) { - $this->{'Time'} = strtotime($this->{'StartTime'}); + $this->{'Time'} = strtotime($this->{'StartDateTime'}); } return $this->{'Time'}; } @@ -153,9 +153,9 @@ class Event extends ZM_Object { if ( $this->{'Scheme'} == 'Deep' ) { # Assumption: All events have a start time - $start_date = date_parse($this->{'StartTime'}); + $start_date = date_parse($this->{'StartDateTime'}); if ( ! $start_date ) { - throw new Exception('Unable to parse start time for event ' . $this->{'Id'} . ' not deleting files.'); + throw new Exception('Unable to parse start date time for event ' . $this->{'Id'} . ' not deleting files.'); } $start_date['year'] = $start_date['year'] % 100; @@ -279,7 +279,7 @@ class Event extends ZM_Object { } if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) { $this->{'DiskSpace'} = folder_size($this->Path()); - if ( $this->{'EndTime'} ) { + if ( $this->{'EndDateTime'} ) { # Finished events shouldn't grow in size much so we can commit it to the db. dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'})); } @@ -606,7 +606,7 @@ class Event extends ZM_Object { if ( $this->Archived() ) { return false; } - if ( !$this->EndTime() ) { + if ( !$this->EndDateTime() ) { return false; } if ( !canEdit('Events') ) { @@ -619,7 +619,7 @@ class Event extends ZM_Object { public function cant_delete_reason() { if ( $this->Archived() ) { return 'You cannot delete an archived event. Unarchive it first.'; - } else if ( ! $this->EndTime() ) { + } else if ( ! $this->EndDateTime() ) { return 'You cannot delete an event while it is being recorded. Wait for it to finish.'; } else if ( ! canEdit('Events') ) { return 'You do not have rights to edit Events.'; diff --git a/web/includes/Filter.php b/web/includes/Filter.php index 20a04c229..84941dbeb 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -392,35 +392,35 @@ class Filter extends ZM_Object { break; case 'DateTime': case 'StartDateTime': - $sqlValue = 'E.StartTime'; + $sqlValue = 'E.StartDateTime'; $dtAttr = true; break; case 'Date': case 'StartDate': - $sqlValue = 'to_days(E.StartTime)'; + $sqlValue = 'to_days(E.StartDateTime)'; $dtAttr = true; break; case 'Time': case 'StartTime': - $sqlValue = 'extract(hour_second from E.StartTime)'; + $sqlValue = 'extract(hour_second from E.StartDateTime)'; break; case 'Weekday': case 'StartWeekday': - $sqlValue = 'weekday(E.StartTime)'; + $sqlValue = 'weekday(E.StartDateTime)'; break; case 'EndDateTime': - $sqlValue = 'E.EndTime'; + $sqlValue = 'E.EndDateTime'; $dtAttr = true; break; case 'EndDate': - $sqlValue = 'to_days(E.EndTime)'; + $sqlValue = 'to_days(E.EndDateTime)'; $dtAttr = true; break; case 'EndTime': - $sqlValue = 'extract(hour_second from E.EndTime)'; + $sqlValue = 'extract(hour_second from E.EndDateTime)'; break; case 'EndWeekday': - $sqlValue = 'weekday(E.EndTime)'; + $sqlValue = 'weekday(E.EndDateTime)'; break; case 'Id': case 'Name': diff --git a/web/includes/FilterTerm.php b/web/includes/FilterTerm.php index ebae24bb5..6b41a2e1d 100644 --- a/web/includes/FilterTerm.php +++ b/web/includes/FilterTerm.php @@ -222,45 +222,45 @@ class FilterTerm { break; # Unspecified start or end, so assume start, this is to support legacy filters case 'DateTime': - $sql .= 'E.StartTime'; + $sql .= 'E.StartDateTime'; break; case 'Date': - $sql .= 'to_days(E.StartTime)'; + $sql .= 'to_days(E.StartDateTime)'; break; case 'Time': - $sql .= 'extract(hour_second FROM E.StartTime)'; + $sql .= 'extract(hour_second FROM E.StartDateTime)'; break; case 'Weekday': - $sql .= 'weekday(E.StartTime)'; + $sql .= 'weekday(E.StartDateTime)'; break; # Starting Time case 'StartDateTime': - $sql .= 'E.StartTime'; + $sql .= 'E.StartDateTime'; break; case 'FramesEventId': $sql .= 'F.EventId'; break; case 'StartDate': - $sql .= 'to_days(E.StartTime)'; + $sql .= 'to_days(E.StartDateTime)'; break; case 'StartTime': - $sql .= 'extract(hour_second FROM E.StartTime)'; + $sql .= 'extract(hour_second FROM E.StartDateTime)'; break; case 'StartWeekday': - $sql .= 'weekday(E.StartTime)'; + $sql .= 'weekday(E.StartDateTime)'; break; # Ending Time case 'EndDateTime': - $sql .= 'E.EndTime'; + $sql .= 'E.EndDateTime'; break; case 'EndDate': - $sql .= 'to_days(E.EndTime)'; + $sql .= 'to_days(E.EndDateTime)'; break; case 'EndTime': - $sql .= 'extract(hour_second FROM E.EndTime)'; + $sql .= 'extract(hour_second FROM E.EndDateTime)'; break; case 'EndWeekday': - $sql .= 'weekday(E.EndTime)'; + $sql .= 'weekday(E.EndDateTime)'; break; case 'Emailed': case 'Id': From 8029f59eac0e2b92e6febfad3b465f7f900ba50b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:52:50 -0500 Subject: [PATCH 121/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/includes/functions.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 725c9baac..9ac46cd3c 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -996,26 +996,19 @@ function parseSort($saveToSession=false, $querySep='&') { $sortColumn = 'E.Cause'; break; case 'DateTime' : - $sortColumn = 'E.StartTime'; - $_REQUEST['sort_field'] = 'StartTime'; + $sortColumn = 'E.StartDateTime'; + $_REQUEST['sort_field'] = 'StartDateTime'; break; case 'DiskSpace' : $sortColumn = 'E.DiskSpace'; break; case 'StartTime' : - $sortColumn = 'E.StartTime'; - break; case 'StartDateTime' : - // Fix for systems with EVENT_SORT_ORDER set to erroneous StartDateTime. - $_REQUEST['sort_field'] = 'StartTime'; - $sortColumn = 'E.StartTime'; + $sortColumn = 'E.StartDateTime'; break; case 'EndTime' : - $sortColumn = 'E.EndTime'; - break; case 'EndDateTime' : - $_REQUEST['sort_field'] = 'EndTime'; - $sortColumn = 'E.EndTime'; + $sortColumn = 'E.EndDateTime'; break; case 'Length' : $sortColumn = 'E.Length'; @@ -1051,7 +1044,7 @@ function parseSort($saveToSession=false, $querySep='&') { $sortColumn = 'F.Score'; break; default: - $sortColumn = 'E.StartTime'; + $sortColumn = 'E.StartDateTime'; break; } if ( !isset($_REQUEST['sort_asc']) ) From 9e6a9cad80669864c103a96449fc3cf17a1402eb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:53:17 -0500 Subject: [PATCH 122/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/event.php | 2 +- web/skins/classic/views/export.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index cb23429f9..24ce53a61 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -145,7 +145,7 @@ if ( !$Event->Id() ) { Id() ?> Id().' '.validHtmlStr($Monitor->Name()) ?> Cause()) ?> - StartTime())) ?> + StartDateTime())) ?> Length().'s' ?> Frames() ?>/AlarmFrames() ?> TotScore() ?>/AvgScore() ?>/MaxScore() ?> diff --git a/web/skins/classic/views/export.php b/web/skins/classic/views/export.php index 90e269a33..e234402f4 100644 --- a/web/skins/classic/views/export.php +++ b/web/skins/classic/views/export.php @@ -152,8 +152,8 @@ while ( $event_row = dbFetchNext($results) ) { Name()).($event->Archived()?'*':'') ?> MonitorId(), $event->MonitorName(), canEdit( 'Monitors' ) ) ?> Cause()), canEdit( 'Events' ), 'title="' .htmlspecialchars($event->Notes()). '" class="eDetailLink" data-eid=' .$event->Id(). '"') ?> - StartTime())) . -( $event->EndTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) : '' ) ?> + StartDateTime())) . +( $event->EndDateTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndDateTime()) ) : '' ) ?> Length() ) ?> Id(), $event->Frames() ) ?> From 9d22de98a34a101602f8ee8971bfd4d54b8898b0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:53:45 -0500 Subject: [PATCH 123/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/js/event.js | 8 ++++---- web/skins/classic/views/js/event.js.php | 4 ++-- web/skins/classic/views/js/montagereview.js.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 143f51ebc..9841ea425 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -16,7 +16,7 @@ function vjsReplay() { var overLaid = $j("#videoobj"); overLaid.append('

No more events

'); } else { - var endTime = (Date.parse(eventData.EndTime)).getTime(); + var endTime = (Date.parse(eventData.EndDateTime)).getTime(); var nextStartTime = nextEventStartTime.getTime(); //nextEventStartTime.getTime() is a mootools workaround, highjacks Date.parse if ( nextStartTime <= endTime ) { streamNext(true); @@ -584,7 +584,7 @@ function getEventResponse(respObj, respText) { $('dataCause').setProperty( 'title', causeString ); } $('dataCause').set( 'text', eventData.Cause ); - $('dataTime').set( 'text', eventData.StartTime ); + $('dataTime').set( 'text', eventData.StartDateTime ); $('dataDuration').set( 'text', eventData.Length ); $('dataFrames').set( 'text', eventData.Frames+"/"+eventData.AlarmFrames ); $('dataScore').set( 'text', eventData.TotScore+"/"+eventData.AvgScore+"/"+eventData.MaxScore ); @@ -606,7 +606,7 @@ function getEventResponse(respObj, respText) { vid.src({type: 'video/mp4', src: CurEventDefVideoPath}); //Currently mp4 is all we use console.log('getEventResponse'); initialAlarmCues(eventData.Id);//ajax and render, new event - addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime); + addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartDateTime); CurEventDefVideoPath = null; $j('#modeValue').html('Replay'); $j('#zoomValue').html('1'); @@ -1088,7 +1088,7 @@ function initPage() { //FIXME prevent blocking...not sure what is happening or best way to unblock if ( $j('#videoobj').length ) { vid = videojs('videoobj'); - addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime); + addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartDateTime); $j('.vjs-progress-control').append('
');//add a place for videojs only on first load vid.on('ended', vjsReplay); vid.on('play', vjsPlay); diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php index beee0b668..105f47da1 100644 --- a/web/skins/classic/views/js/event.js.php +++ b/web/skins/classic/views/js/event.js.php @@ -44,8 +44,8 @@ var eventData = { Width: 'Width() ?>', Height: 'Height() ?>', Length: 'Length() ?>', - StartTime: 'StartTime() ?>', - EndTime: 'EndTime() ?>', + StartDateTime: 'StartDateTime() ?>', + EndDateTime: 'EndDateTime() ?>', Frames: 'Frames() ?>', MonitorName: 'Name()) ?>' }; diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php index d2277b507..9a2206bc6 100644 --- a/web/skins/classic/views/js/montagereview.js.php +++ b/web/skins/classic/views/js/montagereview.js.php @@ -76,7 +76,7 @@ if ( !$liveMode ) { if ( !isset($event['FramesById']) ) { // Please note that this is the last frame as we sort DESC $event['FramesById'] = array(); - $frame['NextTimeStampSecs'] = $event['EndTime']; + $frame['NextTimeStampSecs'] = $event['EndTimeSecs']; } else { $frame['NextTimeStampSecs'] = $next_frames[$frame['EventId']]['TimeStampSecs']; $frame['NextFrameId'] = $next_frames[$frame['EventId']]['Id']; From d75e93249c1a0f0a5e624f57a63a3d78945cc660 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:54:12 -0500 Subject: [PATCH 124/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/js/timeline.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/timeline.js b/web/skins/classic/views/js/timeline.js index 85c73baa6..3eacc2529 100644 --- a/web/skins/classic/views/js/timeline.js +++ b/web/skins/classic/views/js/timeline.js @@ -24,7 +24,7 @@ function createEventHtml(zm_event, frame) { new Element('p').inject(eventHtml).set('text', monitors[zm_event.MonitorId].Name); new Element('p').inject(eventHtml).set('text', zm_event.Name+(frame?('('+frame.FrameId+')'):'')); - new Element('p').inject(eventHtml).set('text', zm_event.StartTime+' - '+zm_event.Length+'s'); + new Element('p').inject(eventHtml).set('text', zm_event.StartDateTime+' - '+zm_event.Length+'s'); new Element('p').inject(eventHtml).set('text', zm_event.Cause); if ( zm_event.Notes ) { new Element('p').inject(eventHtml).set('text', zm_event.Notes); @@ -90,7 +90,7 @@ function showEventData(eventId, frameId) { showEventDetail( zm_event['frames'][frameId]['html'] ); var imagePath = 'index.php?view=image&eid='+eventId+'&fid='+frameId; var videoName = zm_event.DefaultVideo; - loadEventImage( imagePath, eventId, frameId, zm_event.Width, zm_event.Height, zm_event.Frames/zm_event.Length, videoName, zm_event.Length, zm_event.StartTime, monitors[zm_event.MonitorId]); + loadEventImage( imagePath, eventId, frameId, zm_event.Width, zm_event.Height, zm_event.Frames/zm_event.Length, videoName, zm_event.Length, zm_event.StartDateTime, monitors[zm_event.MonitorId]); return; } else { console.log('No frames for ' + frameId); From af9e279f9e73223a1971d410c73bd63deee077a0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:55:27 -0500 Subject: [PATCH 125/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/js/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 23629514e..feea5e698 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -603,7 +603,7 @@ function getEventCmdResponse( respObj, respText ) { link.set('text', zm_event.Name); link.inject(row.getElement('td.colName')); - row.getElement('td.colTime').set('text', zm_event.StartTime); + row.getElement('td.colTime').set('text', zm_event.StartDateTime); row.getElement('td.colSecs').set('text', zm_event.Length); link = new Element('a', {'href': '#', 'events': {'click': openFrames.pass( [zm_event.Id] )}}); From 786e2fec92e6b4ae3f0c79dd44e00ff3b2faa2e1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:56:27 -0500 Subject: [PATCH 126/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/montagereview.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 615a04c0c..d34ee44b4 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -114,19 +114,19 @@ if ( count($filter) ) { $eventsSql = 'SELECT E.Id,E.Name,E.StorageId, - E.StartTime AS StartTime,UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs, - CASE WHEN E.EndTime IS NULL THEN (SELECT NOW()) ELSE E.EndTime END AS EndTime, - UNIX_TIMESTAMP(EndTime) AS EndTimeSecs, + E.StartDateTime AS StartDateTime,UNIX_TIMESTAMP(E.StartDateTime) AS StartTimeSecs, + CASE WHEN E.EndDateTime IS NULL THEN (SELECT NOW()) ELSE E.EndDateTime END AS EndDateTime, + UNIX_TIMESTAMP(EndDateTime) AS EndTimeSecs, E.Length, E.Frames, E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId FROM Events AS E WHERE 1 > 0 '; -// select E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartTime, Interval Delta+0.5 Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId +// select E.Id,E.Name,UNIX_TIMESTAMP(E.StartDateTime) as StartTimeSecs,UNIX_TIMESTAMP(max(DATE_ADD(E.StartDateTime, Interval Delta+0.5 Second))) as CalcEndTimeSecs, E.Length,max(F.FrameId) as Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId // from Events as E // inner join Monitors as M on (E.MonitorId = M.Id) // inner join Frames F on F.EventId=E.Id -// where not isnull(E.Frames) and not isnull(StartTime) "; +// where not isnull(E.Frames) and not isnull(StartDateTime) "; // Note that the delta value seems more accurate than the time stamp for some reason. $framesSql = ' @@ -219,14 +219,14 @@ $initialDisplayInterval = 1000; if ( isset($_REQUEST['displayinterval']) ) $initialDisplayInterval = validHtmlStr($_REQUEST['displayinterval']); -#$eventsSql .= ' GROUP BY E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId'; +#$eventsSql .= ' GROUP BY E.Id,E.Name,E.StartDateTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId'; $minTimeSecs = $maxTimeSecs = 0; if ( isset($minTime) && isset($maxTime) ) { $minTimeSecs = strtotime($minTime); $maxTimeSecs = strtotime($maxTime); - $eventsSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'"; - $framesSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'"; + $eventsSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'"; + $framesSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'"; $framesSql .= ") AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'"; } else { $framesSql .= ')'; From 68ad1cf1f7383c5c32a42f40a36d1c8e108058a7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:56:37 -0500 Subject: [PATCH 127/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/report_event_audit.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/skins/classic/views/report_event_audit.php b/web/skins/classic/views/report_event_audit.php index 46c4dc90d..3dfc08a70 100644 --- a/web/skins/classic/views/report_event_audit.php +++ b/web/skins/classic/views/report_event_audit.php @@ -65,8 +65,8 @@ $filterQuery = $filter['query']; ZM\Debug($filterQuery); $eventsSql = 'SELECT *, - UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs, - UNIX_TIMESTAMP(EndTime) AS EndTimeSecs + UNIX_TIMESTAMP(E.StartDateTime) AS StartTimeSecs, + UNIX_TIMESTAMP(EndDateTime) AS EndTimeSecs FROM Events AS E WHERE 1 > 0 '; @@ -77,7 +77,7 @@ if ( count($selected_monitor_ids) ) { $eventsSql .= ' AND MonitorId IN ('.implode(',', $selected_monitor_ids).')'; } if ( isset($minTime) && isset($maxTime) ) { - $eventsSql .= " AND EndTime > '" . $minTime . "' AND StartTime < '" . $maxTime . "'"; + $eventsSql .= " AND EndDateTime > '" . $minTime . "' AND StartDateTime < '" . $maxTime . "'"; } $eventsSql .= ' ORDER BY Id ASC'; @@ -211,8 +211,8 @@ for ( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) { Server()->Name())?> Id()])?count($EventsByMonitor[$Monitor->Id()]['Events']):0 ?> - link_to($FirstEvent->Id().' at '.$FirstEvent->StartTime()) : 'none'?> - link_to($LastEvent->Id().' at '.$LastEvent->StartTime()) : 'none'?> + link_to($FirstEvent->Id().' at '.$FirstEvent->StartDateTime()) : 'none'?> + link_to($LastEvent->Id().' at '.$LastEvent->StartDateTime()) : 'none'?> From ce99a9456b2ee49e4e15d2032922b0e499c782c6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:56:44 -0500 Subject: [PATCH 128/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/skins/classic/views/timeline.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/skins/classic/views/timeline.php b/web/skins/classic/views/timeline.php index 264c8128e..c4f11d312 100644 --- a/web/skins/classic/views/timeline.php +++ b/web/skins/classic/views/timeline.php @@ -128,9 +128,9 @@ $chart = array( $monitors = array(); # The as E, and joining with Monitors is required for the filterSQL filters. -$rangeSql = 'SELECT min(E.StartTime) AS MinTime, max(E.EndTime) AS MaxTime FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(E.StartTime) AND NOT isnull(E.EndTime)'; -$eventsSql = 'SELECT E.* FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartTime)'; -$eventIdsSql = 'SELECT E.Id FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartTime)'; +$rangeSql = 'SELECT min(E.StartDateTime) AS MinTime, max(E.EndDateTime) AS MaxTime FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(E.StartDateTime) AND NOT isnull(E.EndDateTime)'; +$eventsSql = 'SELECT E.* FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartDateTime)'; +$eventIdsSql = 'SELECT E.Id FROM Events AS E INNER JOIN Monitors AS M ON (E.MonitorId = M.Id) WHERE NOT isnull(StartDateTime)'; $eventsValues = array(); if ( !empty($user['MonitorIds']) ) { @@ -277,8 +277,8 @@ $midTimeT = $minTimeT + $halfRange; $midTime = strftime(STRF_FMT_DATETIME_DB, $midTimeT); if ( isset($minTime) && isset($maxTime) ) { - $eventsSql .= " AND EndTime >= '$minTime' AND StartTime <= '$maxTime'"; - $eventIdsSql .= " AND EndTime >= '$minTime' AND StartTime <= '$maxTime'"; + $eventsSql .= " AND EndDateTime >= '$minTime' AND StartDateTime <= '$maxTime'"; + $eventIdsSql .= " AND EndDateTime >= '$minTime' AND StartDateTime <= '$maxTime'"; } if ( 0 ) { @@ -332,13 +332,13 @@ while( $event = $events_result->fetch(PDO::FETCH_ASSOC) ) { $currEventSlots = &$monEventSlots[$event['MonitorId']]; $currFrameSlots = &$monFrameSlots[$event['MonitorId']]; - $startTimeT = strtotime($event['StartTime']); + $startTimeT = strtotime($event['StartDateTime']); $startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']); if ( $startIndex < 0 ) $startIndex = 0; - if ( isset($event['EndTime']) ) - $endTimeT = strtotime($event['EndTime']); + if ( isset($event['EndDateTime']) ) + $endTimeT = strtotime($event['EndDateTime']); else $endTimeT = time(); $endIndex = $rawEndIndex = (int)(($endTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']); From b17fa8f9c1c944f76e71567a0781680484d1b606 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 13:58:03 -0500 Subject: [PATCH 129/169] Rename StartTime, EndTime in Events to StartDateTime and EndDateTime --- web/ajax/events.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/ajax/events.php b/web/ajax/events.php index bf4cbacdf..5d58a5a41 100644 --- a/web/ajax/events.php +++ b/web/ajax/events.php @@ -39,7 +39,7 @@ $search = isset($_REQUEST['search']) ? $_REQUEST['search'] : ''; $advsearch = isset($_REQUEST['advsearch']) ? json_decode($_REQUEST['advsearch'], JSON_OBJECT_AS_ARRAY) : array(); // Sort specifies the name of the column to sort on -$sort = 'StartTime'; +$sort = 'StartDateTime'; if ( isset($_REQUEST['sort']) ) { $sort = $_REQUEST['sort']; } @@ -133,7 +133,7 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $table = 'Events'; // The names of the dB columns in the events table we are interested in - $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartTime', 'EndTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace'); + $columns = array('Id', 'MonitorId', 'StorageId', 'Name', 'Cause', 'StartDateTime', 'EndDateTime', 'Length', 'Frames', 'AlarmFrames', 'TotScore', 'AvgScore', 'MaxScore', 'Archived', 'Emailed', 'Notes', 'DiskSpace'); // The names of columns shown in the event view that are NOT dB columns in the database $col_alt = array('Monitor', 'Storage'); @@ -212,8 +212,8 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim $row['Archived'] = $row['Archived'] ? translate('Yes') : translate('No'); $row['Emailed'] = $row['Emailed'] ? translate('Yes') : translate('No'); $row['Cause'] = validHtmlStr($row['Cause']); - $row['StartTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartTime'])); - $row['EndTime'] = $row['EndTime'] ? strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndTime'])) : null; + $row['StartDateTime'] = strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['StartDateTime'])); + $row['EndDateTime'] = $row['EndDateTime'] ? strftime(STRF_FMT_DATETIME_SHORTER, strtotime($row['EndDateTime'])) : null; $row['Length'] = gmdate('H:i:s', $row['Length'] ); $row['Storage'] = ( $row['StorageId'] and isset($StorageById[$row['StorageId']]) ) ? $StorageById[$row['StorageId']]->Name() : 'Default'; $row['Notes'] = nl2br(htmlspecialchars($row['Notes'])); From c3d43838da2a3407b67b128465a7721d4ca5e7ee Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 14:41:32 -0500 Subject: [PATCH 130/169] Update StartTime to StartDateTime and EndTime to EndDateTime --- db/zm_update-1.35.13.sql | 101 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 db/zm_update-1.35.13.sql diff --git a/db/zm_update-1.35.13.sql b/db/zm_update-1.35.13.sql new file mode 100644 index 000000000..4f0bf8d24 --- /dev/null +++ b/db/zm_update-1.35.13.sql @@ -0,0 +1,101 @@ +/* DateTime is invalid and it being set here will cause warnings because it isn't in the dropdown set of values in Filter edit. */ +UPDATE Config SET Value='StartDateTime' WHERE Name='ZM_WEB_EVENT_SORT_FIELD' AND Value='DateTime'; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Events' + AND column_name = 'StartDateTime' + ) > 0, +"SELECT 'Column StartDateTime already exists in Events'", +"ALTER TABLE Events RENAME COLUMN StartTime TO StartDateTime" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Events' + AND column_name = 'EndDateTime' + ) > 0, + "SELECT 'Column EndDateTime already exists in Events'", + "ALTER TABLE Events RENAME COLUMN EndTime TO EndDateTime" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Events_Hour' + AND column_name = 'StartDateTime' + ) > 0, + "SELECT 'Column StartDateTime already exists in Events_Hour'", + "ALTER TABLE Events_Hour RENAME COLUMN StartTime TO StartDateTime" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Events_Day' + AND column_name = 'StartDateTime' + ) > 0, + "SELECT 'Column StartDateTime already exists in Events_Day'", + "ALTER TABLE Events_Day RENAME COLUMN StartTime TO StartDateTime" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Events_Week' + AND column_name = 'StartDateTime' + ) > 0, + "SELECT 'Column StartDateTime already exists in Events_Week'", + "ALTER TABLE Events_Week RENAME COLUMN StartTime TO StartDateTime" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Events_Month' + AND column_name = 'StartDateTime' + ) > 0, + "SELECT 'Column StartDateTime already exists in Events_Month'", + "ALTER TABLE Events_Month RENAME COLUMN StartTime TO StartDateTime" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +delimiter // + +DROP TRIGGER IF EXISTS event_insert_trigger// + +/* The assumption is that when an Event is inserted, it has no size yet, so don't bother updating the DiskSpace, just the count. + * The DiskSpace will get update in the Event Update Trigger + */ +CREATE TRIGGER event_insert_trigger AFTER INSERT ON Events +FOR EACH ROW + BEGIN + + INSERT INTO Events_Hour (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Day (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Week (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Month (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + UPDATE Monitors SET + HourEvents = COALESCE(HourEvents,0)+1, + DayEvents = COALESCE(DayEvents,0)+1, + WeekEvents = COALESCE(WeekEvents,0)+1, + MonthEvents = COALESCE(MonthEvents,0)+1, + TotalEvents = COALESCE(TotalEvents,0)+1 + WHERE Id=NEW.MonitorId; +END; +// + +delimiter ; From 3e5f87cb41e6d4903809296d1e65dcbccf596b36 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 14:42:01 -0500 Subject: [PATCH 131/169] Bump version to 1.35.13 --- distros/redhat/zoneminder.spec | 2 +- version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index eefba559d..220f38652 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -28,7 +28,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.35.12 +Version: 1.35.13 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/version b/version index 7d872edd4..8cf7685bd 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.35.12 +1.35.13 From 018abe39c250c4f8ea63446a29426b1482d16afa Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 18:11:24 -0500 Subject: [PATCH 132/169] Use rename commands that work on mysql 5.7 --- db/zm_update-1.35.13.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/db/zm_update-1.35.13.sql b/db/zm_update-1.35.13.sql index 4f0bf8d24..2911aaf65 100644 --- a/db/zm_update-1.35.13.sql +++ b/db/zm_update-1.35.13.sql @@ -7,7 +7,7 @@ SET @s = (SELECT IF( AND column_name = 'StartDateTime' ) > 0, "SELECT 'Column StartDateTime already exists in Events'", -"ALTER TABLE Events RENAME COLUMN StartTime TO StartDateTime" +"ALTER TABLE Events CHANGE StartTime StartDateTime datetime default NULL" )); PREPARE stmt FROM @s; @@ -19,7 +19,7 @@ SET @s = (SELECT IF( AND column_name = 'EndDateTime' ) > 0, "SELECT 'Column EndDateTime already exists in Events'", - "ALTER TABLE Events RENAME COLUMN EndTime TO EndDateTime" + "ALTER TABLE Events CHANGE EndTime EndDateTime datetime default NULL" )); PREPARE stmt FROM @s; @@ -31,7 +31,7 @@ SET @s = (SELECT IF( AND column_name = 'StartDateTime' ) > 0, "SELECT 'Column StartDateTime already exists in Events_Hour'", - "ALTER TABLE Events_Hour RENAME COLUMN StartTime TO StartDateTime" + "ALTER TABLE Events_Hour CHANGE StartTime StartDateTime datetime default NULL" )); PREPARE stmt FROM @s; @@ -43,7 +43,7 @@ SET @s = (SELECT IF( AND column_name = 'StartDateTime' ) > 0, "SELECT 'Column StartDateTime already exists in Events_Day'", - "ALTER TABLE Events_Day RENAME COLUMN StartTime TO StartDateTime" + "ALTER TABLE Events_Day CHANGE StartTime StartDateTime datetime default NULL" )); PREPARE stmt FROM @s; @@ -55,7 +55,7 @@ SET @s = (SELECT IF( AND column_name = 'StartDateTime' ) > 0, "SELECT 'Column StartDateTime already exists in Events_Week'", - "ALTER TABLE Events_Week RENAME COLUMN StartTime TO StartDateTime" + "ALTER TABLE Events_Week CHANGE StartTime StartDateTime datetime default NULL" )); PREPARE stmt FROM @s; @@ -67,7 +67,7 @@ SET @s = (SELECT IF( AND column_name = 'StartDateTime' ) > 0, "SELECT 'Column StartDateTime already exists in Events_Month'", - "ALTER TABLE Events_Month RENAME COLUMN StartTime TO StartDateTime" + "ALTER TABLE Events_Month CHANGE StartTime StartDateTime datetime default NULL" )); PREPARE stmt FROM @s; From d37bce4e0ea99aaaaeaaaf44ab703d9ef1903511 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 18:20:59 -0500 Subject: [PATCH 133/169] Fix missed StartTime to StartDateTime --- web/api/app/Controller/Component/ImageComponent.php | 4 ++-- web/api/app/Controller/EventsController.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/api/app/Controller/Component/ImageComponent.php b/web/api/app/Controller/Component/ImageComponent.php index 2033e0d8c..567333a71 100644 --- a/web/api/app/Controller/Component/ImageComponent.php +++ b/web/api/app/Controller/Component/ImageComponent.php @@ -89,11 +89,11 @@ class ImageComponent extends Component { } - // Take the StartTime of an Event and return + // Take the StartDateTime of an Event and return // the path to its location on the filesystem public function getEventPath( $event ) { if ( $config['ZM_USE_DEEP_STORAGE'] == 1 ) - return $event['Event']['MonitorId'].'/'.strftime( "%y/%m/%d/%H/%M/%S", strtotime($event['Event']['StartTime']) ); + return $event['Event']['MonitorId'].'/'.strftime( '%y/%m/%d/%H/%M/%S', strtotime($event['Event']['StartDateTime']) ); else return $event['Event']['MonitorId'].'/'.$event['Event']['Id']; } diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php index 3b132e932..021c40b5e 100644 --- a/web/api/app/Controller/EventsController.php +++ b/web/api/app/Controller/EventsController.php @@ -65,7 +65,7 @@ class EventsController extends AppController { // API 'limit' => '100', - 'order' => array('StartTime'), + 'order' => array('StartDateTime'), 'paramType' => 'querystring', ); if ( isset($conditions['GroupId']) ) { @@ -309,7 +309,7 @@ class EventsController extends AppController { } else { $conditions = array(); } - array_push($conditions, array("StartTime >= DATE_SUB(NOW(), INTERVAL $expr $unit)")); + array_push($conditions, array("StartDateTime >= DATE_SUB(NOW(), INTERVAL $expr $unit)")); $query = $this->Event->find('all', array( 'fields' => array( 'MonitorId', From 130588eb8fd763fb0c3cadfa31ad22a910072df2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 18:22:50 -0500 Subject: [PATCH 134/169] fix typos --- web/ajax/stream.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/stream.php b/web/ajax/stream.php index 2c583ba14..cdb67c0f9 100644 --- a/web/ajax/stream.php +++ b/web/ajax/stream.php @@ -128,7 +128,7 @@ if ( sem_acquire($semaphore,1) !== false ) { $data['auth'] = $auth_hash; ZM\Debug("including nw auth hash " . $data['auth']); } else { - ZM\Debug('Not including nw auth hash becase it hashn\'t changed '.$auth_hash); + ZM\Debug('Not including new auth hash becase it hasn\'t changed '.$auth_hash); } } ajaxResponse(array('status'=>$data)); From e085e08caa6a7641567db30f34b3b3adfa3dcdaf Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 18:27:51 -0500 Subject: [PATCH 135/169] Fix missed StartTime to StartDateTime --- web/ajax/status.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/web/ajax/status.php b/web/ajax/status.php index 190d239ad..9d97d34b8 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -109,8 +109,8 @@ $statusData = array( 'Name' => true, 'Cause' => true, 'Notes' => true, - 'StartTime' => true, - 'StartTimeShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), + 'StartDateTime' => true, + 'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), 'EndTime' => true, 'Width' => true, 'Height' => true, @@ -133,8 +133,8 @@ $statusData = array( 'MonitorName' => array('sql' => '(SELECT Monitors.Name FROM Monitors WHERE Monitors.Id = Events.MonitorId)'), 'Name' => true, 'Cause' => true, - 'StartTime' => true, - 'StartTimeShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), + 'StartDateTime' => true, + 'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), 'EndTime' => true, 'Width' => true, 'Height' => true, @@ -180,7 +180,7 @@ $statusData = array( 'EventId' => true, 'Type' => true, 'TimeStamp' => true, - 'TimeStampShort' => array( 'sql' => 'date_format( StartTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), + 'TimeStampShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), 'Delta' => true, 'Score' => true, //'Image' => array( 'postFunc' => 'getFrameImage' ), @@ -424,11 +424,11 @@ function getNearEvents() { } # When listing, it may make sense to list them in descending order. But when viewing Prev should timewise earlier and Next should be after. - if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartTime' ) { + if ( $sortColumn == 'E.Id' or $sortColumn == 'E.StartDateTime' ) { $sortOrder = 'ASC'; } - $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\' AND ('.$filter->sql().') AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC'); + $sql = 'SELECT E.Id AS Id, E.StartDateTime AS StartDateTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn.' '.($sortOrder=='ASC'?'<=':'>=').' \''.$event[$_REQUEST['sort_field']].'\' AND ('.$filter->sql().') AND E.Id<'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'DESC':'ASC'); if ( $sortColumn != 'E.Id' ) { # When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id $sql .= ', E.Id DESC'; @@ -442,7 +442,7 @@ function getNearEvents() { $prevEvent = dbFetchNext($result); - $sql = 'SELECT E.Id AS Id, E.StartTime AS StartTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."' AND (".$filter->sql().') AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC'); + $sql = 'SELECT E.Id AS Id, E.StartDateTime AS StartDateTime FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE '.$sortColumn .' '.($sortOrder=='ASC'?'>=':'<=').' \''.$event[$_REQUEST['sort_field']]."' AND (".$filter->sql().') AND E.Id>'.$event['Id'] . ' ORDER BY '.$sortColumn.' '.($sortOrder=='ASC'?'ASC':'DESC'); if ( $sortColumn != 'E.Id' ) { # When sorting by starttime, if we have two events with the same starttime (diffreent monitors) then we should sort secondly by Id $sql .= ', E.Id ASC'; @@ -457,14 +457,14 @@ function getNearEvents() { if ( $prevEvent ) { $NearEvents['PrevEventId'] = $prevEvent['Id']; - $NearEvents['PrevEventStartTime'] = $prevEvent['StartTime']; + $NearEvents['PrevEventStartTime'] = $prevEvent['StartDateTime']; $NearEvents['PrevEventDefVideoPath'] = getEventDefaultVideoPath($prevEvent['Id']); } else { $NearEvents['PrevEventId'] = $NearEvents['PrevEventStartTime'] = $NearEvents['PrevEventDefVideoPath'] = 0; } if ( $nextEvent ) { $NearEvents['NextEventId'] = $nextEvent['Id']; - $NearEvents['NextEventStartTime'] = $nextEvent['StartTime']; + $NearEvents['NextEventStartTime'] = $nextEvent['StartDateTime']; $NearEvents['NextEventDefVideoPath'] = getEventDefaultVideoPath($nextEvent['Id']); } else { $NearEvents['NextEventId'] = $NearEvents['NextEventStartTime'] = $NearEvents['NextEventDefVideoPath'] = 0; From ee89eb45e66658abe00e24d47dcfa94f0c1d4905 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Nov 2020 18:39:02 -0500 Subject: [PATCH 136/169] Fix EndTime to EndDateTime --- web/ajax/status.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/ajax/status.php b/web/ajax/status.php index 9d97d34b8..795a4b581 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -111,7 +111,7 @@ $statusData = array( 'Notes' => true, 'StartDateTime' => true, 'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), - 'EndTime' => true, + 'EndDateTime' => true, 'Width' => true, 'Height' => true, 'Length' => true, @@ -135,7 +135,7 @@ $statusData = array( 'Cause' => true, 'StartDateTime' => true, 'StartTimeShort' => array( 'sql' => 'date_format( StartDateTime, \''.MYSQL_FMT_DATETIME_SHORT.'\' )' ), - 'EndTime' => true, + 'EndDateTime' => true, 'Width' => true, 'Height' => true, 'Length' => true, From c4eb59442e4767d53b8b052add1a1d5d511ae46e Mon Sep 17 00:00:00 2001 From: Esteban Flores Date: Mon, 2 Nov 2020 01:05:57 -0600 Subject: [PATCH 137/169] Changed "Purge By Age" filter Changed "Purge By Age" filter, the "date" option is not available in v1.34.22. Using "End Date" as the filter parameter works just fine. --- docs/faq.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 56b67d082..1db30e05f 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -27,7 +27,7 @@ After you've done that, you changes will automatically be loaded into zmfilter w Check the ``zmfilter.log`` file to make sure it is running as sometimes missing perl modules mean that it never runs but people don't always realize. **Purge By Age** -To delete events that are older than 7 days, create a new filter with "Date" set to "less than" and a value of "-7 days", sort by "date/time" in "asc"ending order, then enable the checkbox "delete all matches". You can also use a value of week or week and days: "-2 week" or "-2 week 4 day" +To delete events that are older than 7 days, create a new filter with "End Date" set to "less than" and a value of "-7 days", sort by "date/time" in "asc"ending order, then enable the checkbox "delete all matches". You can also use a value of week or week and days: "-2 week" or "-2 week 4 day" Save with 'Run Filter In Background' enabled to have it run automatically. Optional skip archived events: click on the plus sign next to -7 days to add another condition. "and" "archive status" equal to "unarchived only". @@ -534,4 +534,4 @@ The GPL license allows you produce systems based on GPL software provided your s I am having issues with zmNinja and/or Event Notification Server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -zmNinja and the Event Notification Server are 3rd party solutions. The developer maintains exhaustive `documentation and FAQs `__. Please direct your questions there. \ No newline at end of file +zmNinja and the Event Notification Server are 3rd party solutions. The developer maintains exhaustive `documentation and FAQs `__. Please direct your questions there. From 746882ba85fe8a5b0c763a20a06d86659f6dd697 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 5 Nov 2020 13:45:02 -0500 Subject: [PATCH 138/169] Get rid of zmEventScaleAuto cookie. Just use the per monitor zmEventScale cookie. Fixes #3070 --- web/skins/classic/views/event.php | 3 --- web/skins/classic/views/js/event.js | 7 +------ 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index b9c2d8f38..231a60430 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -46,9 +46,6 @@ if ( isset($_REQUEST['rate']) ) { if ( isset($_REQUEST['scale']) ) { $scale = validInt($_REQUEST['scale']); -} else if ( isset($_COOKIE['zmEventScaleAuto']) ) { - // If we're using scale to fit use it on all monitors - $scale = '0'; } else if ( isset($_COOKIE['zmEventScale'.$Event->MonitorId()]) ) { $scale = $_COOKIE['zmEventScale'.$Event->MonitorId()]; } else { diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index efc9360da..ef79125f0 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -175,12 +175,7 @@ function changeScale() { } else { alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call } - if ( scale = '0' || scale == 'auto' ) { - Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365}); - } else { - Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365}); - Cookie.dispose('zmEventScaleAuto'); - } + Cookie.write('zmEventScale'+eventData.MonitorId, scale, {duration: 10*365}); } function changeReplayMode() { From 402b559b2cbc08c42395e4eaf6463798f2c79c5d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 11:15:12 -0500 Subject: [PATCH 139/169] Add StartTime and EndTime virtual fields for backwards compatability --- web/api/app/Model/Event.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/api/app/Model/Event.php b/web/api/app/Model/Event.php index 22a97f62f..e54fd125f 100644 --- a/web/api/app/Model/Event.php +++ b/web/api/app/Model/Event.php @@ -31,6 +31,10 @@ class Event extends AppModel { */ public $displayField = 'Name'; + public $virtualFields = array( + 'StartTime' => 'StartDateTime', + 'EndTime' => 'EndDateTime' + ); //The Associations below have been created with all possible keys, those that are not needed can be removed From 6ed006bc600bde23ba21a4e37923f5515d3d6477 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 12:25:04 -0500 Subject: [PATCH 140/169] rename StartTime and EndTime to StartDateTime and EndDateTime in the named query params --- web/api/app/Controller/EventsController.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php index 021c40b5e..d18409387 100644 --- a/web/api/app/Controller/EventsController.php +++ b/web/api/app/Controller/EventsController.php @@ -48,9 +48,24 @@ class EventsController extends AppController { $mon_options = ''; } - if ( $this->request->params['named'] ) { + $named_params = $this->request->params['named']; + if ( $named_params ) { + # In 1.35.13 we renamed StartTime and EndTime to StartDateTime and EndDateTime. + # This hack renames the query string params + foreach ( $named_params as $k=>$v ) { + if ( false !== strpos($k, 'StartTime') ) { + $new_k = preg_replace('/StartTime/', 'StartDateTime', $k); + $named_params[$new_k] = $named_params[$k]; + unset($named_params[$k]); + } + if ( false !== strpos($k, 'EndTime') ) { + $new_k = preg_replace('/EndTime/', 'EndDateTime', $k); + $named_params[$new_k] = $named_params[$k]; + unset($named_params[$k]); + } + } $this->FilterComponent = $this->Components->load('Filter'); - $conditions = $this->FilterComponent->buildFilter($this->request->params['named']); + $conditions = $this->FilterComponent->buildFilter($named_params); } else { $conditions = array(); } From 63c78b43f8a6d8496e538a46be1bf52e3b1b3ff3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 13:27:00 -0500 Subject: [PATCH 141/169] Change event stats to Monitor_Status --- db/triggers.sql | 78 ++++++++++++++++++++++----------------------- db/zm_create.sql.in | 24 +++++++------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/db/triggers.sql b/db/triggers.sql index ad697be54..574d34440 100644 --- a/db/triggers.sql +++ b/db/triggers.sql @@ -3,10 +3,10 @@ delimiter // DROP TRIGGER IF EXISTS Events_Hour_delete_trigger// CREATE TRIGGER Events_Hour_delete_trigger BEFORE DELETE ON Events_Hour FOR EACH ROW BEGIN - UPDATE Monitors SET + UPDATE Monitor_Status SET HourEvents = GREATEST(COALESCE(HourEvents,1)-1,0), HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END; // @@ -20,10 +20,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitors SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId; - UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -32,10 +32,10 @@ FOR EACH ROW DROP TRIGGER IF EXISTS Events_Day_delete_trigger// CREATE TRIGGER Events_Day_delete_trigger BEFORE DELETE ON Events_Day FOR EACH ROW BEGIN - UPDATE Monitors SET + UPDATE Monitor_Status SET DayEvents = GREATEST(COALESCE(DayEvents,1)-1,0), DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END; // @@ -48,10 +48,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId; - UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitors SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -61,10 +61,10 @@ FOR EACH ROW DROP TRIGGER IF EXISTS Events_Week_delete_trigger// CREATE TRIGGER Events_Week_delete_trigger BEFORE DELETE ON Events_Week FOR EACH ROW BEGIN - UPDATE Monitors SET + UPDATE Monitor_Status SET WeekEvents = GREATEST(COALESCE(WeekEvents,1)-1,0), WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END; // @@ -77,10 +77,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitors.Id=OLD.MonitorId; - UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitors SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -89,10 +89,10 @@ FOR EACH ROW DROP TRIGGER IF EXISTS Events_Month_delete_trigger// CREATE TRIGGER Events_Month_delete_trigger BEFORE DELETE ON Events_Month FOR EACH ROW BEGIN - UPDATE Monitors SET + UPDATE Monitor_Status SET MonthEvents = GREATEST(COALESCE(MonthEvents,1)-1,0), MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END; // @@ -105,10 +105,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitors.Id=OLD.MonitorId; - UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitors SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitors.Id=NEW.MonitorId; + UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -126,14 +126,14 @@ BEGIN set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( NEW.StorageId = OLD.StorageID ) THEN IF ( diff ) THEN - UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Id = OLD.StorageId; + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Storage.Id = OLD.StorageId; END IF; ELSE IF ( NEW.DiskSpace ) THEN - UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Id = NEW.StorageId; + UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Storage.Id = NEW.StorageId; END IF; IF ( OLD.DiskSpace ) THEN - UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Id = OLD.StorageId; + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Storage.Id = OLD.StorageId; END IF; END IF; @@ -145,20 +145,20 @@ BEGIN IF ( NEW.Archived != OLD.Archived ) THEN IF ( NEW.Archived ) THEN INSERT INTO Events_Archived (EventId,MonitorId,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.DiskSpace); - UPDATE Monitors SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Id=NEW.MonitorId; + UPDATE Monitor_Status SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSEIF ( OLD.Archived ) THEN DELETE FROM Events_Archived WHERE EventId=OLD.Id; - UPDATE Monitors + UPDATE Monitor_Status SET ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0), ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) - WHERE Monitors.Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; ELSE IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; - UPDATE Monitors SET + UPDATE Monitor_Status SET ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0) - WHERE Monitors.Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END IF; END IF; ELSEIF ( NEW.Archived AND diff ) THEN @@ -166,10 +166,10 @@ BEGIN END IF; IF ( diff ) THEN - UPDATE Monitors + UPDATE Monitor_Status SET TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END IF; END; @@ -189,13 +189,13 @@ FOR EACH ROW INSERT INTO Events_Day (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); INSERT INTO Events_Week (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); INSERT INTO Events_Month (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); - UPDATE Monitors SET + UPDATE Monitor_Status SET HourEvents = COALESCE(HourEvents,0)+1, DayEvents = COALESCE(DayEvents,0)+1, WeekEvents = COALESCE(WeekEvents,0)+1, MonthEvents = COALESCE(MonthEvents,0)+1, TotalEvents = COALESCE(TotalEvents,0)+1 - WHERE Id=NEW.MonitorId; + WHERE Monitor_Status.MonitorId=NEW.MonitorId; END; // @@ -205,7 +205,7 @@ CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events FOR EACH ROW BEGIN IF ( OLD.DiskSpace ) THEN - UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Id = OLD.StorageId; + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Storage.Id = OLD.StorageId; END IF; DELETE FROM Events_Hour WHERE EventId=OLD.Id; DELETE FROM Events_Day WHERE EventId=OLD.Id; @@ -213,17 +213,17 @@ BEGIN DELETE FROM Events_Month WHERE EventId=OLD.Id; IF ( OLD.Archived ) THEN DELETE FROM Events_Archived WHERE EventId=OLD.Id; - UPDATE Monitors SET + UPDATE Monitor_Status SET ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,1) - 1,0), ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0), TotalEvents = GREATEST(COALESCE(TotalEvents,1) - 1,0), TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; ELSE - UPDATE Monitors SET + UPDATE Monitor_Status SET TotalEvents = GREATEST(COALESCE(TotalEvents,1)-1,0), TotalEventDiskSpace=GREATEST(COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) - WHERE Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END IF; END; @@ -233,14 +233,14 @@ DROP TRIGGER IF EXISTS Zone_Insert_Trigger// CREATE TRIGGER Zone_Insert_Trigger AFTER INSERT ON Zones FOR EACH ROW BEGIN - UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Id=NEW.MonitorID; + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Monitors.Id=NEW.MonitorID; END // DROP TRIGGER IF EXISTS Zone_Delete_Trigger// CREATE TRIGGER Zone_Delete_Trigger AFTER DELETE ON Zones FOR EACH ROW BEGIN - UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Id=OLD.MonitorID; + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Monitors.Id=OLD.MonitorID; END // diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 40063a74c..8cbd7866d 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -525,18 +525,6 @@ CREATE TABLE `Monitors` ( `WebColour` varchar(32) NOT NULL default 'red', `Exif` tinyint(1) unsigned NOT NULL default '0', `Sequence` smallint(5) unsigned default NULL, - `TotalEvents` int(10) default NULL, - `TotalEventDiskSpace` bigint default NULL, - `HourEvents` int(10) default NULL, - `HourEventDiskSpace` bigint default NULL, - `DayEvents` int(10) default NULL, - `DayEventDiskSpace` bigint default NULL, - `WeekEvents` int(10) default NULL, - `WeekEventDiskSpace` bigint default NULL, - `MonthEvents` int(10) default NULL, - `MonthEventDiskSpace` bigint default NULL, - `ArchivedEvents` int(10) default NULL, - `ArchivedEventDiskSpace` bigint default NULL, `ZoneCount` TINYINT NOT NULL DEFAULT 0, `Refresh` int(10) unsigned default NULL, `Latitude` DECIMAL(10,8), @@ -553,6 +541,18 @@ CREATE TABLE `Monitor_Status` ( `CaptureFPS` DECIMAL(10,2) NOT NULL default 0, `AnalysisFPS` DECIMAL(5,2) NOT NULL default 0, `CaptureBandwidth` INT NOT NULL default 0, + `TotalEvents` int(10) default NULL, + `TotalEventDiskSpace` bigint default NULL, + `HourEvents` int(10) default NULL, + `HourEventDiskSpace` bigint default NULL, + `DayEvents` int(10) default NULL, + `DayEventDiskSpace` bigint default NULL, + `WeekEvents` int(10) default NULL, + `WeekEventDiskSpace` bigint default NULL, + `MonthEvents` int(10) default NULL, + `MonthEventDiskSpace` bigint default NULL, + `ArchivedEvents` int(10) default NULL, + `ArchivedEventDiskSpace` bigint default NULL, PRIMARY KEY (`MonitorId`) ) ENGINE=@ZM_MYSQL_ENGINE@; -- From 159b3832760f4212c8c016c4a4aeb8b86d0f3833 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 13:27:47 -0500 Subject: [PATCH 142/169] Move event stat totals to Monitor_Status. Implement a class for them called Monitor_Status --- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm | 24 ----- .../lib/ZoneMinder/Monitor_Status.pm | 99 +++++++++++++++++++ 2 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Monitor_Status.pm diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm index 55e46e114..80b4fb75a 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm @@ -121,18 +121,6 @@ $serial = $primary_key = 'Id'; WebColour Exif Sequence - TotalEvents - TotalEventDiskSpace - HourEvents - HourEventDiskSpace - DayEvents - DayEventDiskSpace - WeekEvents - WeekEventDiskSpace - MonthEvents - MonthEventDiskSpace - ArchivedEvents - ArchivedEventDiskSpace ZoneCount Refresh DefaultCodec @@ -219,18 +207,6 @@ $serial = $primary_key = 'Id'; WebColour => '#ff0000', Exif => 0, Sequence => undef, - TotalEvents => undef, - TotalEventDiskSpace => undef, - HourEvents => undef, - HourEventDiskSpace => undef, - DayEvents => undef, - DayEventDiskSpace => undef, - WeekEvents => undef, - WeekEventDiskSpace => undef, - MonthEvents => undef, - MonthEventDiskSpace => undef, - ArchivedEvents => undef, - ArchivedEventDiskSpace => undef, ZoneCount => 0, Refresh => undef, DefaultCodec => 'auto', diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Monitor_Status.pm b/scripts/ZoneMinder/lib/ZoneMinder/Monitor_Status.pm new file mode 100644 index 000000000..059c38121 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Monitor_Status.pm @@ -0,0 +1,99 @@ +# ========================================================================== +# +# ZoneMinder Monitor_STatus Module +# Copyright (C) 2020 ZoneMinder +# +# This program 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 2 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ========================================================================== +# +# This module contains the common definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::Monitor_Status; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Object; + +#our @ISA = qw(Exporter ZoneMinder::Base); +use parent qw(ZoneMinder::Object); + +use vars qw/ $table $primary_key %fields $serial %defaults $debug/; +$table = 'Monitor_Status'; +$serial = $primary_key = 'MonitorId'; +%fields = map { $_ => $_ } qw( + MonitorId + TotalEvents + TotalEventDiskSpace + HourEvents + HourEventDiskSpace + DayEvents + DayEventDiskSpace + WeekEvents + WeekEventDiskSpace + MonthEvents + MonthEventDiskSpace + ArchivedEvents + ArchivedEventDiskSpace + ); + +%defaults = ( + TotalEvents => undef, + TotalEventDiskSpace => undef, + HourEvents => undef, + HourEventDiskSpace => undef, + DayEvents => undef, + DayEventDiskSpace => undef, + WeekEvents => undef, + WeekEventDiskSpace => undef, + MonthEvents => undef, + MonthEventDiskSpace => undef, + ArchivedEvents => undef, + ArchivedEventDiskSpace => undef, + ); + +sub Monitor { + return new ZoneMinder::Monitor( $_[0]{MonitorId} ); +} # end sub Monitor + +1; +__END__ + +=head1 NAME + +ZoneMinder::Monitor_Status - Perl Class for Monitor Status + +=head1 SYNOPSIS + +use ZoneMinder::Monitor_Status; + +=head1 AUTHOR + +Isaac Connor, Eisaac@zoneminder.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2001-2017 ZoneMinder LLC + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.8.3 or, +at your option, any later version of Perl 5 you may have available. + + +=cut From 59403dc11b450b6df43e39071d745a54501e3181 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 14:00:18 -0500 Subject: [PATCH 143/169] Move event stat totals to Monitor_Status. --- web/includes/Monitor.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index e858135e6..00735aeda 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -113,18 +113,6 @@ class Monitor extends ZM_Object { 'WebColour' => '#ff0000', 'Exif' => array('type'=>'boolean','default'=>0), 'Sequence' => null, - 'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), 'ZoneCount' => 0, 'Refresh' => null, 'DefaultCodec' => 'auto', @@ -137,6 +125,18 @@ class Monitor extends ZM_Object { 'AnalysisFPS' => null, 'CaptureFPS' => null, 'CaptureBandwidth' => null, + 'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), ); public function Control() { From 98e296a2c8a92153ff8d98942b66b24477b8bcb4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 14:15:05 -0500 Subject: [PATCH 144/169] Move event stat totals to Monitor_Status. --- db/zm_update-1.35.14.sql | 556 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 db/zm_update-1.35.14.sql diff --git a/db/zm_update-1.35.14.sql b/db/zm_update-1.35.14.sql new file mode 100644 index 000000000..c2d02bf49 --- /dev/null +++ b/db/zm_update-1.35.14.sql @@ -0,0 +1,556 @@ + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'TotalEvents' + ) > 0, +"SELECT 'Column TotalEvents already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `TotalEvents` INT(10) AFTER `CaptureBandwidth`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'TotalEvents' + ) > 0, +"SELECT 'Column TotalEvents is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `TotalEvents`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'TotalEventDiskSpace' + ) > 0, +"SELECT 'Column TotalEventDiskSpace already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `TotalEventDiskSpace` BIGINT AFTER `TotalEvents`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'TotalEventDiskSpace' + ) > 0, +"SELECT 'Column TotalEventDiskSpace is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `TotalEventDiskSpace`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'HourEvents' + ) > 0, +"SELECT 'Column HourEvents already exists in Monitors'", +"ALTER TABLE `Monitor_Status` ADD `HourEvents` INT(10) AFTER `TotalEventDiskSpace`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'HourEvents' + ) > 0, +"ALTER TABLE `Monitors` DROP `HourEvents`" +"SELECT 'Column HourEvents is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'HourEventDiskSpace' + ) > 0, +"SELECT 'Column HourEventDiskSpace already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `HourEventDiskSpace` BIGINT AFTER `HourEvents`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'HourEventDiskSpace' + ) > 0, +"ALTER TABLE `Monitors` DROP `HourEventDiskSpace`" +"SELECT 'Column HourEventDiskSpace is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'DayEvents' + ) > 0, +"SELECT 'Column DayEvents already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `DayEvents` INT(10) AFTER `HourEventDiskSpace`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'DayEvents' + ) > 0, +"ALTER TABLE `Monitors` DROP `DayEvents`" +"SELECT 'Column DayEvents is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'DayEventDiskSpace' + ) > 0, +"SELECT 'Column DayEventDiskSpace already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `DayEventDiskSpace` BIGINT AFTER `DayEvents`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'DayEventDiskSpace' + ) > 0, +"ALTER TABLE `Monitors` DROP `DayEventDiskSpace`" +"SELECT 'Column DayEventDiskSpace is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'WeekEvents' + ) > 0, +"SELECT 'Column WeekEvents already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `WeekEvents` INT(10) AFTER `DayEventDiskSpace`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'WeekEvents' + ) > 0, +"ALTER TABLE `Monitors` DROP `WeekEvents`" +"SELECT 'Column WeekEvents is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'WeekEventDiskSpace' + ) > 0, +"SELECT 'Column WeekEventDiskSpace already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `WeekEventDiskSpace` BIGINT AFTER `WeekEvents`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'WeekEventDiskSpace' + ) > 0, +"ALTER TABLE `Monitors` DROP `WeekEventDiskSpace`" +"SELECT 'Column WeekEventDiskSpace is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'MonthEvents' + ) > 0, +"SELECT 'Column MonthEvents already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `MonthEvents` INT(10) AFTER `WeekEventDiskSpace`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'MonthEvents' + ) > 0, +"ALTER TABLE `Monitors` DROP `MonthEvents`" +"SELECT 'Column MonthEvents is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'MonthEventDiskSpace' + ) > 0, +"SELECT 'Column MonthEventDiskSpace already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `MonthEventDiskSpace` BIGINT AFTER `MonthEvents`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'MonthEventDiskSpace' + ) > 0, +"ALTER TABLE `Monitors` DROP `MonthEventDiskSpace`" +"SELECT 'Column MonthEventDiskSpace is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'ArchivedEvents' + ) > 0, +"SELECT 'Column ArchivedEvents already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `ArchivedEvents` INT(10) AFTER `MonthEventDiskSpace`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'ArchivedEvents' + ) > 0, +"ALTER TABLE `Monitors` DROP `ArchivedEvents`" +"SELECT 'Column ArchivedEvents is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + AND column_name = 'ArchivedEventDiskSpace' + ) > 0, +"SELECT 'Column ArchivedEventDiskSpace already exists in Monitor_Status'", +"ALTER TABLE `Monitor_Status` ADD `ArchivedEventDiskSpace` BIGINT AFTER `ArchivedEvents`" +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'ArchivedEventDiskSpace' + ) > 0, +"ALTER TABLE `Monitors` DROP `ArchivedEventDiskSpace`" +"SELECT 'Column ArchivedEventDiskSpace is already removed from Monitors'", +)); +PREPARE stmt FROM @s; +EXECUTE stmt; + +UPDATE Monitor_Status INNER JOIN ( + SELECT MonitorId, + COUNT(Id) AS TotalEvents, + SUM(DiskSpace) AS TotalEventDiskSpace, + SUM(IF(Archived,1,0)) AS ArchivedEvents, + SUM(IF(Archived,DiskSpace,0)) AS ArchivedEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace + FROM Events GROUP BY MonitorId + ) AS E ON E.MonitorId=Monitor_Status.MonitorId SET + Monitor_Status.TotalEvents = E.TotalEvents, + Monitor_Status.TotalEventDiskSpace = E.TotalEventDiskSpace, + Monitor_Status.ArchivedEvents = E.ArchivedEvents, + Monitor_Status.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace, + Monitor_Status.HourEvents = E.HourEvents, + Monitor_Status.HourEventDiskSpace = E.HourEventDiskSpace, + Monitor_Status.DayEvents = E.DayEvents, + Monitor_Status.DayEventDiskSpace = E.DayEventDiskSpace, + Monitor_Status.WeekEvents = E.WeekEvents, + Monitor_Status.WeekEventDiskSpace = E.WeekEventDiskSpace, + Monitor_Status.MonthEvents = E.MonthEvents, + Monitor_Status.MonthEventDiskSpace = E.MonthEventDiskSpace; + + +delimiter // +DROP TRIGGER IF EXISTS Events_Hour_delete_trigger// +CREATE TRIGGER Events_Hour_delete_trigger BEFORE DELETE ON Events_Hour +FOR EACH ROW BEGIN + UPDATE Monitor_Status SET + HourEvents = GREATEST(COALESCE(HourEvents,1)-1,0), + HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) + WHERE Monitor_Status.MonitorId=OLD.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS Events_Hour_update_trigger// + +CREATE TRIGGER Events_Hour_update_trigger AFTER UPDATE ON Events_Hour +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitor_Status SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.Id=OLD.MonitorId; + UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.Id=NEW.MonitorId; + ELSE + UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitor_Status.Id=NEW.MonitorId; + END IF; + END IF; + END; +// + +DROP TRIGGER IF EXISTS Events_Day_delete_trigger// +CREATE TRIGGER Events_Day_delete_trigger BEFORE DELETE ON Events_Day +FOR EACH ROW BEGIN + UPDATE Monitor_Status SET + DayEvents = GREATEST(COALESCE(DayEvents,1)-1,0), + DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) + WHERE Monitor_Status.MonitorId=OLD.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS Events_Day_update_trigger; +CREATE TRIGGER Events_Day_update_trigger AFTER UPDATE ON Events_Day +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.Id=OLD.MonitorId; + UPDATE Monitor_Status SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.Id=NEW.MonitorId; + ELSE + UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitor_Status.Id=NEW.MonitorId; + END IF; + END IF; + END; + // + + +DROP TRIGGER IF EXISTS Events_Week_delete_trigger// +CREATE TRIGGER Events_Week_delete_trigger BEFORE DELETE ON Events_Week +FOR EACH ROW BEGIN + UPDATE Monitor_Status SET + WeekEvents = GREATEST(COALESCE(WeekEvents,1)-1,0), + WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) + WHERE Monitor_Status.MonitorId=OLD.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS Events_Week_update_trigger; +CREATE TRIGGER Events_Week_update_trigger AFTER UPDATE ON Events_Week +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.Id=OLD.MonitorId; + UPDATE Monitor_Status SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.Id=NEW.MonitorId; + ELSE + UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitor_Status.Id=NEW.MonitorId; + END IF; + END IF; + END; + // + +DROP TRIGGER IF EXISTS Events_Month_delete_trigger// +CREATE TRIGGER Events_Month_delete_trigger BEFORE DELETE ON Events_Month +FOR EACH ROW BEGIN + UPDATE Monitor_Status SET + MonthEvents = GREATEST(COALESCE(MonthEvents,1)-1,0), + MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) + WHERE Monitor_Status.MonitorId=OLD.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS Events_Month_update_trigger; +CREATE TRIGGER Events_Month_update_trigger AFTER UPDATE ON Events_Month +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitor_Status.Id=OLD.MonitorId; + UPDATE Monitor_Status SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitor_Status.Id=NEW.MonitorId; + ELSE + UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitor_Status.Id=NEW.MonitorId; + END IF; + END IF; + END; + // + +drop procedure if exists update_storage_stats// + +drop trigger if exists event_update_trigger// + +CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events +FOR EACH ROW +BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( NEW.StorageId = OLD.StorageID ) THEN + IF ( diff ) THEN + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Monitor_Status.MonitorId = OLD.StorageId; + END IF; + ELSE + IF ( NEW.DiskSpace ) THEN + UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Monitor_Status.MonitorId = NEW.StorageId; + END IF; + IF ( OLD.DiskSpace ) THEN + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Monitor_Status.MonitorId = OLD.StorageId; + END IF; + END IF; + + UPDATE Events_Hour SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Day SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Week SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Month SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + + IF ( NEW.Archived != OLD.Archived ) THEN + IF ( NEW.Archived ) THEN + INSERT INTO Events_Archived (EventId,MonitorId,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.DiskSpace); + UPDATE Monitor_Status SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; + ELSEIF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitor_Status + SET + ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0), + ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) + WHERE Monitor_Status.Id=OLD.MonitorId; + ELSE + IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN + UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Monitor_Status SET + ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0) + WHERE Monitor_Status.Id=OLD.MonitorId; + END IF; + END IF; + ELSEIF ( NEW.Archived AND diff ) THEN + UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + END IF; + + IF ( diff ) THEN + UPDATE Monitor_Status + SET + TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0) + WHERE Monitor_Status.MonitorId=OLD.MonitorId; + END IF; + +END; + +// + +DROP TRIGGER IF EXISTS event_insert_trigger// + +/* The assumption is that when an Event is inserted, it has no size yet, so don't bother updating the DiskSpace, just the count. + * The DiskSpace will get update in the Event Update Trigger + */ +CREATE TRIGGER event_insert_trigger AFTER INSERT ON Events +FOR EACH ROW + BEGIN + + INSERT INTO Events_Hour (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Day (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Week (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + INSERT INTO Events_Month (EventId,MonitorId,StartDateTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartDateTime,0); + UPDATE Monitor_Status SET + HourEvents = COALESCE(HourEvents,0)+1, + DayEvents = COALESCE(DayEvents,0)+1, + WeekEvents = COALESCE(WeekEvents,0)+1, + MonthEvents = COALESCE(MonthEvents,0)+1, + TotalEvents = COALESCE(TotalEvents,0)+1 + WHERE Monitor_Status.MonitorId=NEW.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS event_delete_trigger// + +CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events +FOR EACH ROW +BEGIN + IF ( OLD.DiskSpace ) THEN + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId = OLD.StorageId; + END IF; + DELETE FROM Events_Hour WHERE EventId=OLD.Id; + DELETE FROM Events_Day WHERE EventId=OLD.Id; + DELETE FROM Events_Week WHERE EventId=OLD.Id; + DELETE FROM Events_Month WHERE EventId=OLD.Id; + IF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitor_Status SET + ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,1) - 1,0), + ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0), + TotalEvents = GREATEST(COALESCE(TotalEvents,1) - 1,0), + TotalEventDiskSpace = GREATEST(COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) + WHERE Monitor_Status.MonitorId=OLD.MonitorId; + ELSE + UPDATE Monitor_Status SET + TotalEvents = GREATEST(COALESCE(TotalEvents,1)-1,0), + TotalEventDiskSpace=GREATEST(COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) + WHERE Monitor_Status.MonitorId=OLD.MonitorId; + END IF; +END; + +// + +DELIMITER ; + +UPDATE Monitor_Status INNER JOIN ( + SELECT MonitorId, + COUNT(Id) AS TotalEvents, + SUM(DiskSpace) AS TotalEventDiskSpace, + SUM(IF(Archived,1,0)) AS ArchivedEvents, + SUM(IF(Archived,DiskSpace,0)) AS ArchivedEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents, + SUM(IF(StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace + FROM Events GROUP BY MonitorId + ) AS E ON E.MonitorId=Monitor_Status.MonitorId SET + Monitor_Status.TotalEvents = E.TotalEvents, + Monitor_Status.TotalEventDiskSpace = E.TotalEventDiskSpace, + Monitor_Status.ArchivedEvents = E.ArchivedEvents, + Monitor_Status.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace, + Monitor_Status.HourEvents = E.HourEvents, + Monitor_Status.HourEventDiskSpace = E.HourEventDiskSpace, + Monitor_Status.DayEvents = E.DayEvents, + Monitor_Status.DayEventDiskSpace = E.DayEventDiskSpace, + Monitor_Status.WeekEvents = E.WeekEvents, + Monitor_Status.WeekEventDiskSpace = E.WeekEventDiskSpace, + Monitor_Status.MonthEvents = E.MonthEvents, + Monitor_Status.MonthEventDiskSpace = E.MonthEventDiskSpace; From a3a6d94b6ffe36d67b040448c401949beae996e6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 14:16:34 -0500 Subject: [PATCH 145/169] bump version to 1.15.14 --- distros/redhat/zoneminder.spec | 2 +- version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 220f38652..af62cefba 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -28,7 +28,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.35.13 +Version: 1.35.14 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/version b/version index 8cf7685bd..31d4ef08d 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.35.13 +1.35.14 From 691ff5881d5d796d9f05674366921d5f1db525d6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 14:28:11 -0500 Subject: [PATCH 146/169] Fix some commas --- db/zm_update-1.35.14.sql | 41 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/db/zm_update-1.35.14.sql b/db/zm_update-1.35.14.sql index c2d02bf49..c473cdc39 100644 --- a/db/zm_update-1.35.14.sql +++ b/db/zm_update-1.35.14.sql @@ -59,8 +59,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'HourEvents' ) > 0, -"ALTER TABLE `Monitors` DROP `HourEvents`" -"SELECT 'Column HourEvents is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `HourEvents`", +"SELECT 'Column HourEvents is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -81,8 +81,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'HourEventDiskSpace' ) > 0, -"ALTER TABLE `Monitors` DROP `HourEventDiskSpace`" -"SELECT 'Column HourEventDiskSpace is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `HourEventDiskSpace`", +"SELECT 'Column HourEventDiskSpace is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -103,8 +103,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'DayEvents' ) > 0, -"ALTER TABLE `Monitors` DROP `DayEvents`" -"SELECT 'Column DayEvents is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `DayEvents`", +"SELECT 'Column DayEvents is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -125,8 +125,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'DayEventDiskSpace' ) > 0, -"ALTER TABLE `Monitors` DROP `DayEventDiskSpace`" -"SELECT 'Column DayEventDiskSpace is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `DayEventDiskSpace`", +"SELECT 'Column DayEventDiskSpace is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -147,8 +147,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'WeekEvents' ) > 0, -"ALTER TABLE `Monitors` DROP `WeekEvents`" -"SELECT 'Column WeekEvents is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `WeekEvents`", +"SELECT 'Column WeekEvents is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -169,8 +169,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'WeekEventDiskSpace' ) > 0, -"ALTER TABLE `Monitors` DROP `WeekEventDiskSpace`" -"SELECT 'Column WeekEventDiskSpace is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `WeekEventDiskSpace`", +"SELECT 'Column WeekEventDiskSpace is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -191,8 +191,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'MonthEvents' ) > 0, -"ALTER TABLE `Monitors` DROP `MonthEvents`" -"SELECT 'Column MonthEvents is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `MonthEvents`", +"SELECT 'Column MonthEvents is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -208,14 +208,13 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; - SET @s = (SELECT IF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() AND table_name = 'Monitors' AND column_name = 'MonthEventDiskSpace' ) > 0, -"ALTER TABLE `Monitors` DROP `MonthEventDiskSpace`" -"SELECT 'Column MonthEventDiskSpace is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `MonthEventDiskSpace`", +"SELECT 'Column MonthEventDiskSpace is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -236,8 +235,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'ArchivedEvents' ) > 0, -"ALTER TABLE `Monitors` DROP `ArchivedEvents`" -"SELECT 'Column ArchivedEvents is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `ArchivedEvents`", +"SELECT 'Column ArchivedEvents is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; @@ -258,8 +257,8 @@ SET @s = (SELECT IF( AND table_name = 'Monitors' AND column_name = 'ArchivedEventDiskSpace' ) > 0, -"ALTER TABLE `Monitors` DROP `ArchivedEventDiskSpace`" -"SELECT 'Column ArchivedEventDiskSpace is already removed from Monitors'", +"ALTER TABLE `Monitors` DROP `ArchivedEventDiskSpace`", +"SELECT 'Column ArchivedEventDiskSpace is already removed from Monitors'" )); PREPARE stmt FROM @s; EXECUTE stmt; From 2e7aa178828b5bd2d2f579cd782cdf1568fb0272 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 14:32:21 -0500 Subject: [PATCH 147/169] Fix triggers that update Storage --- db/zm_update-1.35.14.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/db/zm_update-1.35.14.sql b/db/zm_update-1.35.14.sql index c473cdc39..c961fe0c2 100644 --- a/db/zm_update-1.35.14.sql +++ b/db/zm_update-1.35.14.sql @@ -420,14 +420,14 @@ BEGIN set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( NEW.StorageId = OLD.StorageID ) THEN IF ( diff ) THEN - UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Monitor_Status.MonitorId = OLD.StorageId; + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) + diff,0) WHERE Storage.Id = OLD.StorageId; END IF; ELSE IF ( NEW.DiskSpace ) THEN - UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Monitor_Status.MonitorId = NEW.StorageId; + UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Storage.Id = NEW.StorageId; END IF; IF ( OLD.DiskSpace ) THEN - UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Monitor_Status.MonitorId = OLD.StorageId; + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - OLD.DiskSpace,0) WHERE Storage.Id = OLD.StorageId; END IF; END IF; @@ -499,7 +499,7 @@ CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events FOR EACH ROW BEGIN IF ( OLD.DiskSpace ) THEN - UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId = OLD.StorageId; + UPDATE Storage SET DiskSpace = GREATEST(COALESCE(DiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) WHERE Storage.Id = OLD.StorageId; END IF; DELETE FROM Events_Hour WHERE EventId=OLD.Id; DELETE FROM Events_Day WHERE EventId=OLD.Id; From 4b4863c44ac75beb6f510b7e84b17f13fd4a53bc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Nov 2020 16:07:40 -0500 Subject: [PATCH 148/169] Fix remaining references to MonitorStatus.Id --- db/zm_update-1.35.14.sql | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/db/zm_update-1.35.14.sql b/db/zm_update-1.35.14.sql index c961fe0c2..46a6d2445 100644 --- a/db/zm_update-1.35.14.sql +++ b/db/zm_update-1.35.14.sql @@ -314,10 +314,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitor_Status SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.Id=OLD.MonitorId; - UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET HourEventDiskSpace=GREATEST(COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -342,10 +342,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.Id=OLD.MonitorId; - UPDATE Monitor_Status SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET DayEventDiskSpace=GREATEST(COALESCE(DayEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -371,10 +371,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.Id=OLD.MonitorId; - UPDATE Monitor_Status SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET WeekEventDiskSpace=GREATEST(COALESCE(WeekEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -399,10 +399,10 @@ FOR EACH ROW set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); IF ( diff ) THEN IF ( NEW.MonitorID != OLD.MonitorID ) THEN - UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitor_Status.Id=OLD.MonitorId; - UPDATE Monitor_Status SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace),0) WHERE Monitor_Status.MonitorId=OLD.MonitorId; + UPDATE Monitor_Status SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitor_Status.MonitorId=NEW.MonitorId; ELSE - UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitor_Status.Id=NEW.MonitorId; + UPDATE Monitor_Status SET MonthEventDiskSpace=GREATEST(COALESCE(MonthEventDiskSpace,0)+diff,0) WHERE Monitor_Status.MonitorId=NEW.MonitorId; END IF; END IF; END; @@ -446,13 +446,13 @@ BEGIN SET ArchivedEvents = GREATEST(COALESCE(ArchivedEvents,0)-1,0), ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0),0) - WHERE Monitor_Status.Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; ELSE IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; UPDATE Monitor_Status SET ArchivedEventDiskSpace = GREATEST(COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0),0) - WHERE Monitor_Status.Id=OLD.MonitorId; + WHERE Monitor_Status.MonitorId=OLD.MonitorId; END IF; END IF; ELSEIF ( NEW.Archived AND diff ) THEN From b3e3fea79f711d4942c4f37fdda3d8d2b84729a5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Nov 2020 12:26:14 -0500 Subject: [PATCH 149/169] Update summary event count tables --- db/zm_update-1.35.14.sql | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/db/zm_update-1.35.14.sql b/db/zm_update-1.35.14.sql index 46a6d2445..7c9b39d99 100644 --- a/db/zm_update-1.35.14.sql +++ b/db/zm_update-1.35.14.sql @@ -525,6 +525,12 @@ END; DELIMITER ; +REPLACE INTO Events_Hour SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 hour); +REPLACE INTO Events_Day SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 day); +REPLACE INTO Events_Week SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 week); +REPLACE INTO Events_Month SELECT Id,MonitorId,StartDateTime,DiskSpace FROM Events WHERE StartDateTime > DATE_SUB(NOW(), INTERVAL 1 month); +REPLACE INTO Events_Archived SELECT Id,MonitorId,DiskSpace FROM Events WHERE Archived=1; + UPDATE Monitor_Status INNER JOIN ( SELECT MonitorId, COUNT(Id) AS TotalEvents, From cda3824a257969a0f1c33862f863fe006bd4d420 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Nov 2020 12:33:10 -0500 Subject: [PATCH 150/169] Use INSERT.. ON DUPLICATE... instead of REPLACE INTO. REPLACE INTO deletes the existing row. Since we now have event counts in there, we lose them. --- src/zmc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/zmc.cpp b/src/zmc.cpp index 8376c91ba..e11745e43 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -243,8 +243,8 @@ int main(int argc, char *argv[]) { time_t now = (time_t)time(nullptr); monitors[i]->setStartupTime(now); - snprintf(sql, sizeof(sql), - "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Running')", + snprintf(sql, sizeof(sql), + "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Running') ON DUPLICATE KEY UPDATE Status='Running'", monitors[i]->Id()); if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn)); @@ -273,7 +273,7 @@ int main(int argc, char *argv[]) { capture_delays[i] = monitors[i]->GetCaptureDelay(); alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay(); snprintf(sql, sizeof(sql), - "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','Connected')", + "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='Connected'", monitors[i]->Id()); if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn)); @@ -364,7 +364,7 @@ int main(int argc, char *argv[]) { for ( int i = 0; i < n_monitors; i++ ) { static char sql[ZM_SQL_SML_BUFSIZ]; snprintf(sql, sizeof(sql), - "REPLACE INTO Monitor_Status (MonitorId, Status) VALUES ('%d','NotRunning')", + "INSERT INTO Monitor_Status (MonitorId,Status) VALUES (%d, 'Connected') ON DUPLICATE KEY UPDATE Status='NotRunning'", monitors[i]->Id()); if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn)); From 8f456e7c3daa3655a2711d0169f868f328633590 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Nov 2020 12:38:10 -0500 Subject: [PATCH 151/169] Add a useful warning message regarding the update needing SUPER prvilege --- db/zm_update-1.35.14.sql | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/db/zm_update-1.35.14.sql b/db/zm_update-1.35.14.sql index 7c9b39d99..daa8239ff 100644 --- a/db/zm_update-1.35.14.sql +++ b/db/zm_update-1.35.14.sql @@ -1,3 +1,16 @@ +SELECT 'This update may make changes that require SUPER privileges. If you see an error message saying: + +ERROR 1419 (HY000) at line 298: You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) + +You will have to either run this update as root manually using something like (on ubuntu/debian) + +sudo mysql --defaults-file=/etc/mysql/debian.cnf zm < /usr/share/zoneminder/db/zm_update-1.35.14.sql + +OR + +sudo mysql --defaults-file=/etc/mysql/debian.cnf "set global log_bin_trust_function_creators=1;" +sudo zmupdate.pl +'; SET @s = (SELECT IF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() From 5b10fff2a0e8f04873c2d35b453aa219236b91c3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Nov 2020 13:14:36 -0500 Subject: [PATCH 152/169] Use cached objects when using new instead of only find_one --- web/includes/Object.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/web/includes/Object.php b/web/includes/Object.php index e8fff930b..aa571bb59 100644 --- a/web/includes/Object.php +++ b/web/includes/Object.php @@ -11,7 +11,16 @@ class ZM_Object { $row = NULL; if ( $IdOrRow ) { + global $object_cache; + if ( ! isset($object_cache[$class]) ) { + $object_cache[$class] = array(); + } + $cache = &$object_cache[$class]; + if ( is_integer($IdOrRow) or ctype_digit($IdOrRow) ) { + if ( isset($cache[$IdOrRow]) ) { + return $cache[$IdOrRow]; + } $table = $class::$table; $row = dbFetchOne("SELECT * FROM `$table` WHERE `Id`=?", NULL, array($IdOrRow)); if ( !$row ) { @@ -22,12 +31,6 @@ class ZM_Object { } if ( $row ) { - global $object_cache; - if ( ! isset($object_cache[$class]) ) { - $object_cache[$class] = array(); - } - $cache = &$object_cache[$class]; - foreach ($row as $k => $v) { $this->{$k} = $v; } From b4aacde5bfdcc393c2815393b54dc54db4c28bb5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Nov 2020 13:15:46 -0500 Subject: [PATCH 153/169] Remove debug. Auth is pretty solid these days --- web/includes/auth.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/includes/auth.php b/web/includes/auth.php index 0268b0018..a4e1e4268 100644 --- a/web/includes/auth.php +++ b/web/includes/auth.php @@ -254,8 +254,6 @@ function userFromSession() { $sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?'; $user = dbFetchOne($sql, NULL, array($_SESSION['username'])); } - } else { - ZM\Debug('No username in session'); } return $user; } From 330023f65b529b9d2026a85847fdddb059d205ed Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 09:30:39 -0500 Subject: [PATCH 154/169] Move Events totals to Monitor_Status instead of Monitors --- scripts/zmaudit.pl.in | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index 4601ea1aa..eb17faef5 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -885,7 +885,7 @@ FROM `Frames` WHERE `EventId`=?'; $loop = $continuous; my $eventcounts_sql = ' - UPDATE `Monitors` SET + UPDATE `Monitor_Status` SET `TotalEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id`), `TotalEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `DiskSpace` IS NOT NULL), `ArchivedEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `Archived`=1), @@ -897,40 +897,40 @@ FROM `Frames` WHERE `EventId`=?'; $eventcounts_sth->finish(); my $eventcounts_hour_sql = ' - UPDATE `Monitors` INNER JOIN ( + UPDATE `Monitor_Status` INNER JOIN ( SELECT `MonitorId`, COUNT(*) AS `HourEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `HourEventDiskSpace` FROM `Events_Hour` GROUP BY `MonitorId` - ) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET - `Monitors`.`HourEvents` = `E`.`HourEvents`, - `Monitors`.`HourEventDiskSpace` = `E`.`HourEventDiskSpace` + ) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET + `Monitor_Status`.`HourEvents` = `E`.`HourEvents`, + `Monitor_Status`.`HourEventDiskSpace` = `E`.`HourEventDiskSpace` '; my $eventcounts_day_sql = ' - UPDATE `Monitors` INNER JOIN ( + UPDATE `Monitor_Status` INNER JOIN ( SELECT `MonitorId`, COUNT(*) AS `DayEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `DayEventDiskSpace` FROM `Events_Day` GROUP BY `MonitorId` - ) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET - `Monitors`.`DayEvents` = `E`.`DayEvents`, - `Monitors`.`DayEventDiskSpace` = `E`.`DayEventDiskSpace` + ) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET + `Monitor_Status`.`DayEvents` = `E`.`DayEvents`, + `Monitor_Status`.`DayEventDiskSpace` = `E`.`DayEventDiskSpace` '; my $eventcounts_week_sql = ' - UPDATE `Monitors` INNER JOIN ( + UPDATE `Monitor_Status` INNER JOIN ( SELECT `MonitorId`, COUNT(*) AS `WeekEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `WeekEventDiskSpace` FROM `Events_Week` GROUP BY `MonitorId` - ) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET - `Monitors`.`WeekEvents` = `E`.`WeekEvents`, - `Monitors`.`WeekEventDiskSpace` = `E`.`WeekEventDiskSpace` + ) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET + `Monitor_Status`.`WeekEvents` = `E`.`WeekEvents`, + `Monitor_Status`.`WeekEventDiskSpace` = `E`.`WeekEventDiskSpace` '; my $eventcounts_month_sql = ' - UPDATE `Monitors` INNER JOIN ( + UPDATE `Monitor_Status` INNER JOIN ( SELECT `MonitorId`, COUNT(*) AS `MonthEvents`, SUM(COALESCE(`DiskSpace`,0)) AS `MonthEventDiskSpace` FROM `Events_Month` GROUP BY `MonitorId` - ) AS `E` ON `E`.`MonitorId`=`Monitors`.`Id` SET - `Monitors`.`MonthEvents` = `E`.`MonthEvents`, - `Monitors`.`MonthEventDiskSpace` = `E`.`MonthEventDiskSpace` + ) AS `E` ON `E`.`MonitorId`=`Monitor_Status`.`MonitorId` SET + `Monitor_Status`.`MonthEvents` = `E`.`MonthEvents`, + `Monitor_Status`.`MonthEventDiskSpace` = `E`.`MonthEventDiskSpace` '; my $eventcounts_hour_sth = $dbh->prepare_cached($eventcounts_hour_sql); my $eventcounts_day_sth = $dbh->prepare_cached($eventcounts_day_sql); From 0aef0adf48716eaf9f0dbd321099bf6aa8ce93b6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 11:32:54 -0500 Subject: [PATCH 155/169] Fix more Monitors.Id => Monitor_Status.MonitorId --- scripts/zmaudit.pl.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index eb17faef5..29ff7cab9 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -886,10 +886,10 @@ FROM `Frames` WHERE `EventId`=?'; my $eventcounts_sql = ' UPDATE `Monitor_Status` SET - `TotalEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id`), - `TotalEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `DiskSpace` IS NOT NULL), - `ArchivedEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `Archived`=1), - `ArchivedEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitors`.`Id` AND `Archived`=1 AND `DiskSpace` IS NOT NULL) + `TotalEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId`), + `TotalEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId` AND `DiskSpace` IS NOT NULL), + `ArchivedEvents`=(SELECT COUNT(`Id`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId` AND `Archived`=1), + `ArchivedEventDiskSpace`=(SELECT SUM(`DiskSpace`) FROM `Events` WHERE `MonitorId`=`Monitor_Status`.`MonitorId` AND `Archived`=1 AND `DiskSpace` IS NOT NULL) '; my $eventcounts_sth = $dbh->prepare_cached( $eventcounts_sql ); From 52c7cc5869484ef967654b29dbd25567d90b989f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 11:49:44 -0500 Subject: [PATCH 156/169] reorganize code. Remove Server caching as it is done in Object.php. --- web/ajax/log.php | 100 ++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 54 deletions(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index 22897fd04..60f0c1dc4 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -1,12 +1,13 @@ "search text" pairs -// Bootstrap table sends json_ecoded array, which we must decode -$advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); - -// Sort specifies the name of the column to sort on -$sort = 'TimeKey'; -if ( isset($_REQUEST['sort']) ) { - $sort = $_REQUEST['sort']; - if ( $sort == 'DateTime' ) $sort = 'TimeKey'; -} - -// 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']; - } -} - -// 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 = 100; -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 // @@ -69,7 +33,7 @@ switch ( $task ) { createRequest(); break; case 'query' : - $data = queryRequest($search, $advsearch, $sort, $offset, $order, $limit); + $data = queryRequest(); break; default : ZM\Fatal('Unrecognised task '.$task); @@ -105,9 +69,27 @@ function createRequest() { } } -function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { - global $Servers; +function queryRequest() { + // 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']; + } + } + + // Limit specifies the number of rows to return + $limit = 100; + 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']; + } + } // The table we want our data from $table = 'Logs'; @@ -117,11 +99,19 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { // The names of columns shown in the log view that are NOT dB columns in the database $col_alt = array('DateTime', 'Server'); + $sort = 'TimeKey'; + if ( isset($_REQUEST['sort']) ) { + $sort = $_REQUEST['sort']; + if ( $sort == 'DateTime' ) $sort = 'TimeKey'; + } if ( !in_array($sort, array_merge($columns, $col_alt)) ) { ZM\Error('Invalid sort field: ' . $sort); return; } + // Order specifies the sort direction, either asc or desc + $order = (isset($_REQUEST['order']) and (strtolower($_REQUEST['order']) == 'asc')) ? 'ASC' : 'DESC'; + $col_str = implode(', ', $columns); $data = array(); $query = array(); @@ -131,11 +121,17 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { // 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 + // + // Advanced search contains an array of "column name" => "search text" pairs + // Bootstrap table sends json_ecoded array, which we must decode + $advsearch = isset($_REQUEST['filter']) ? json_decode($_REQUEST['filter'], JSON_OBJECT_AS_ARRAY) : array(); + // Search contains a user entered string to search on + $search = isset($_REQUEST['search']) ? $_REQUEST['search'] : ''; if ( count($advsearch) ) { foreach ( $advsearch as $col=>$text ) { if ( !in_array($col, array_merge($columns, $col_alt)) ) { - ZM\Error("'$col' is not a sortable column name"); + ZM\Error("'$col' is not a searchable column name"); continue; } // Don't use wildcards on advanced search @@ -160,8 +156,6 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $query['sql'] = 'SELECT ' .$col_str. ' FROM `' .$table. '` ' .$where. ' ORDER BY ' .$sort. ' ' .$order. ' LIMIT ?, ?'; array_push($query['values'], $offset, $limit); - //ZM\Warning('Calling the following sql query: ' .$query['sql']); - $data['totalNotFiltered'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table, 'Total'); if ( $search != '' || count($advsearch) ) { $data['total'] = dbFetchOne('SELECT count(*) AS Total FROM ' .$table.$where , 'Total', $wherevalues); @@ -169,18 +163,16 @@ function queryRequest($search, $advsearch, $sort, $offset, $order, $limit) { $data['total'] = $data['totalNotFiltered']; } - if ( !$Servers ) - $Servers = ZM\Server::find(); - $servers_by_Id = array(); - # There is probably a better way to do this. - foreach ( $Servers as $server ) { - $servers_by_Id[$server->Id()] = $server; + $rows = array(); + $results = dbFetchAll($query['sql'], NULL, $query['values']); + if ( !$results ) { + return $data; } - $rows = array(); - foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $row ) { + foreach ( $results as $row ) { $row['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($row['TimeKey'])); - $row['Server'] = ( $row['ServerId'] and isset($servers_by_Id[$row['ServerId']]) ) ? $servers_by_Id[$row['ServerId']]->Name() : ''; + $Server = new ZM\Server($row['ServerId']); + $row['Server'] = $Server->Name(); // First strip out any html tags // Second strip out all characters that are not ASCII 32-126 (yes, 126) $row['Message'] = preg_replace('/[^\x20-\x7E]/', '', strip_tags($row['Message'])); From 736e108b66f33eda18fab4a6618101b8c02b2ee5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 12:04:55 -0500 Subject: [PATCH 157/169] Revert to FriendsOfCake instead of our fork, as they have merged our patch. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index eb0e282a2..9f21bb62b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "web/api/app/Plugin/Crud"] path = web/api/app/Plugin/Crud - url = https://github.com/ZoneMinder/crud.git + url = https://github.com/FriendsOfCake/crud.git branch = 3.0 [submodule "web/api/app/Plugin/CakePHP-Enum-Behavior"] path = web/api/app/Plugin/CakePHP-Enum-Behavior From d663683f47386c3641128c1c1468c4a82c113e5d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 12:43:41 -0500 Subject: [PATCH 158/169] Add a bunch of debug statements to figure out crash --- src/zm_event.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index cd7ba1918..ed478ad20 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -255,7 +255,7 @@ Event::~Event() { } // endtime is set in AddFrame, so SHOULD be set to the value of the last frame timestamp. - if ( ! end_time.tv_sec ) { + if ( !end_time.tv_sec ) { Warning("Empty endtime for event. Should not happen. Setting to now."); gettimeofday(&end_time, nullptr); } @@ -503,7 +503,7 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) { } // void Event::updateNotes(const StringSetMap &newNoteSetMap) void Event::AddFrames(int n_frames, Image **images, struct timeval **timestamps) { - for (int i = 0; i < n_frames; i += ZM_SQL_BATCH_SIZE) { + for ( int i = 0; i < n_frames; i += ZM_SQL_BATCH_SIZE ) { AddFramesInternal(n_frames, i, images, timestamps); } } @@ -592,6 +592,7 @@ void Event::WriteDbFrames() { frame->delta.fsec, frame->score); delete frame; + Debug(1, "SQL: %s", frame_insert_sql); } *(frame_insert_values_ptr-1) = '\0'; // The -1 is for the extra , added for values above db_mutex.lock(); @@ -600,6 +601,8 @@ void Event::WriteDbFrames() { db_mutex.unlock(); if ( rc ) { + Error("Can't insert frames: rc %d", rc); + Error("Can't insert frames: sql %s", frame_insert_sql); Error("Can't insert frames: %s, sql was %s", mysql_error(&dbconn), frame_insert_sql); return; } else { @@ -719,6 +722,9 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a db_mutex.lock(); } db_mutex.unlock(); + } else { + Debug(1, "Not Adding %d frames to DB because write_to_db:%d or frames > analysis fps %f or BULK", + frame_data.size(), write_to_db, monitor->get_fps()); } // end if frame_type == BULK } // end if db_frame From f855f207e261c5755758ecc41e1a94889cb97fbe Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 14:03:08 -0500 Subject: [PATCH 159/169] Limit that # of db frames to buffer to 120 because the sql will exceed 8192. --- src/zm_event.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index ed478ad20..c858b1877 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -39,6 +39,7 @@ //#define USE_PREPARED_SQL 1 const char * Event::frame_type_names[3] = { "Normal", "Bulk", "Alarm" }; +#define MAX_DB_FRAMES 120 char frame_insert_sql[ZM_SQL_LGE_BUFSIZ] = "INSERT INTO `Frames` (`EventId`, `FrameId`, `Type`, `TimeStamp`, `Delta`, `Score`) VALUES "; int Event::pre_alarm_count = 0; @@ -577,6 +578,9 @@ void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, str void Event::WriteDbFrames() { char *frame_insert_values_ptr = (char *)&frame_insert_sql + 90; // 90 == strlen(frame_insert_sql); + + /* Each frame needs about 63 chars. So if we buffer too many frames, we will exceed the size of frame_insert_sql; + */ Debug(1, "Inserting %d frames", frame_data.size()); while ( frame_data.size() ) { Frame *frame = frame_data.front(); @@ -592,17 +596,13 @@ void Event::WriteDbFrames() { frame->delta.fsec, frame->score); delete frame; - Debug(1, "SQL: %s", frame_insert_sql); } *(frame_insert_values_ptr-1) = '\0'; // The -1 is for the extra , added for values above db_mutex.lock(); - Debug(1, "SQL: %s", frame_insert_sql); int rc = mysql_query(&dbconn, frame_insert_sql); db_mutex.unlock(); if ( rc ) { - Error("Can't insert frames: rc %d", rc); - Error("Can't insert frames: sql %s", frame_insert_sql); Error("Can't insert frames: %s, sql was %s", mysql_error(&dbconn), frame_insert_sql); return; } else { @@ -691,14 +691,23 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a Debug(1, "Frame delta is %d.%d - %d.%d = %d.%d", start_time.tv_sec, start_time.tv_usec, timestamp.tv_sec, timestamp.tv_usec, delta_time.sec, delta_time.fsec); + double fps = monitor->get_fps(); + bool db_frame = ( frame_type != BULK ) || (frames==1) || ((frames%config.bulk_frame_interval)==0) ; if ( db_frame ) { // The idea is to write out 1/sec frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time, score)); - if ( write_to_db or ( monitor->get_fps() and (frame_data.size() > monitor->get_fps())) or frame_type==BULK ) { + if ( write_to_db + or + (frame_data.size() > MAX_DB_FRAMES) + or + (frame_type==BULK) + or + ( fps and (frame_data.size() > fps) ) + ) { Debug(1, "Adding %d frames to DB because write_to_db:%d or frames > analysis fps %f or BULK", - frame_data.size(), write_to_db, monitor->get_fps()); + frame_data.size(), write_to_db, fps); WriteDbFrames(); last_db_frame = frames; @@ -724,7 +733,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a db_mutex.unlock(); } else { Debug(1, "Not Adding %d frames to DB because write_to_db:%d or frames > analysis fps %f or BULK", - frame_data.size(), write_to_db, monitor->get_fps()); + frame_data.size(), write_to_db, fps); } // end if frame_type == BULK } // end if db_frame From 4fdf7f79aee9a8509bf46c532970ee4622a209ec Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 16:05:58 -0500 Subject: [PATCH 160/169] Include Record monitors in zmtrigger. --- scripts/zmtrigger.pl.in | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 1ee392c1e..be38c5e91 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -187,7 +187,7 @@ while (1) { } else { Fatal("Can't select: $!"); } - } # end if select returned activitiy + } # end if select returned activity # Check polled connections foreach my $connection ( @in_poll_connections ) { @@ -266,7 +266,7 @@ while (1) { Debug('Checking for timed actions'); my $now = time(); foreach my $action_time ( sort( grep { $_ < $now } @action_times ) ) { - Info("Found " . scalar @{$actions{$action_time}} . "actions expiring at $action_time"); + Info('Found '.(scalar @{$actions{$action_time}}).'actions expiring at '.$action_time); foreach my $action ( @{$actions{$action_time}} ) { my $connection = $action->{connection}; Info("Found action '$$action{message}'"); @@ -319,7 +319,7 @@ exit; sub loadMonitor { my $monitor = shift; - Debug("Loading monitor $monitor"); + Debug('Loading monitor '.$monitor); zmMemInvalidate($monitor); if ( zmMemVerify($monitor) ) { # This will re-init shared memory @@ -334,7 +334,7 @@ sub loadMonitors { my %new_monitors = (); my $sql = 'SELECT * FROM `Monitors` - WHERE find_in_set( `Function`, \'Modect,Mocord,Nodect\' )'. + WHERE find_in_set( `Function`, \'Modect,Mocord,Nodect,Record\' )'. ( $Config{ZM_SERVER_ID} ? ' AND `ServerId`=?' : '' ) ; my $sth = $dbh->prepare_cached( $sql ) @@ -387,12 +387,9 @@ sub handleMessage { } # Force a reload $monitor_reload_time = 0; - Info("Set monitor to $state"); + Info('Set monitor to '.$state); if ( $delay ) { - my $action_text = $id.'|'.( ($state eq 'enable') - ? 'disable' - : 'enable' - ); + my $action_text = $id.'|'.(($state eq 'enable') ? 'disable' : 'enable'); handleDelay($delay, $connection, $action_text); } } elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) { From 076d649189f2dcdf3b79d2b59c5c84514e27f3b3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 16:12:30 -0500 Subject: [PATCH 161/169] Include Record Monitors in zmtrigger --- scripts/zmtrigger.pl.in | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 1ee392c1e..be38c5e91 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -187,7 +187,7 @@ while (1) { } else { Fatal("Can't select: $!"); } - } # end if select returned activitiy + } # end if select returned activity # Check polled connections foreach my $connection ( @in_poll_connections ) { @@ -266,7 +266,7 @@ while (1) { Debug('Checking for timed actions'); my $now = time(); foreach my $action_time ( sort( grep { $_ < $now } @action_times ) ) { - Info("Found " . scalar @{$actions{$action_time}} . "actions expiring at $action_time"); + Info('Found '.(scalar @{$actions{$action_time}}).'actions expiring at '.$action_time); foreach my $action ( @{$actions{$action_time}} ) { my $connection = $action->{connection}; Info("Found action '$$action{message}'"); @@ -319,7 +319,7 @@ exit; sub loadMonitor { my $monitor = shift; - Debug("Loading monitor $monitor"); + Debug('Loading monitor '.$monitor); zmMemInvalidate($monitor); if ( zmMemVerify($monitor) ) { # This will re-init shared memory @@ -334,7 +334,7 @@ sub loadMonitors { my %new_monitors = (); my $sql = 'SELECT * FROM `Monitors` - WHERE find_in_set( `Function`, \'Modect,Mocord,Nodect\' )'. + WHERE find_in_set( `Function`, \'Modect,Mocord,Nodect,Record\' )'. ( $Config{ZM_SERVER_ID} ? ' AND `ServerId`=?' : '' ) ; my $sth = $dbh->prepare_cached( $sql ) @@ -387,12 +387,9 @@ sub handleMessage { } # Force a reload $monitor_reload_time = 0; - Info("Set monitor to $state"); + Info('Set monitor to '.$state); if ( $delay ) { - my $action_text = $id.'|'.( ($state eq 'enable') - ? 'disable' - : 'enable' - ); + my $action_text = $id.'|'.(($state eq 'enable') ? 'disable' : 'enable'); handleDelay($delay, $connection, $action_text); } } elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) { From 73e8c04b6f32df882d8f6066b84e3a2cfd1dbd6d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 17:39:20 -0500 Subject: [PATCH 162/169] Fix encoding of = in filter['Id']. Fixes redirect after saving --- web/includes/Filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Filter.php b/web/includes/Filter.php index 84941dbeb..c4610de4d 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -61,7 +61,7 @@ class Filter extends ZM_Object { $this->_querystring .= $term->querystring($objectname, $separator); } # end foreach term if ( $this->Id() ) { - $this->_querystring .= $separator.$objectname.urlencode('[Id]=').$this->Id(); + $this->_querystring .= $separator.$objectname.urlencode('[Id]').'='.$this->Id(); } } return $this->_querystring; From fe733fe1e6e352f7129567a5dea9c587cfef48c6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 17:39:37 -0500 Subject: [PATCH 163/169] Must use & instead of & in filter redirect --- web/includes/actions/filter.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/includes/actions/filter.php b/web/includes/actions/filter.php index 572cccf08..9216ef723 100644 --- a/web/includes/actions/filter.php +++ b/web/includes/actions/filter.php @@ -46,7 +46,6 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) { } } else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) { - $sql = ''; $_REQUEST['filter']['Query']['sort_field'] = validStr($_REQUEST['filter']['Query']['sort_field']); $_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']); $_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']); @@ -95,7 +94,7 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) { } else if ( $filter->Background() ) { $filter->control('start'); } - $redirect = '?view=filter'.$filter->querystring(); + $redirect = '?view=filter'.$filter->querystring('filter', '&'); } else if ( $action == 'control' ) { if ( $_REQUEST['command'] == 'start' From 95f8aad19b673e3f4167dc95fc607b96033bb1e7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 17:39:55 -0500 Subject: [PATCH 164/169] Fix detection of filter['id'] --- web/skins/classic/views/filter.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index fe90681b3..723414f6e 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -37,8 +37,8 @@ $filter = NULL; $fid = 0; if ( isset($_REQUEST['Id']) and $_REQUEST['Id'] ) { $fid = validInt($_REQUEST['Id']); -} else if ( isset($_REQUEST['filter[Id]']) ) { - $fid = validInt($_REQUEST['filter[Id]']); +} else if ( isset($_REQUEST['filter']) and isset($_REQUEST['filter']['Id']) ) { + $fid = validInt($_REQUEST['filter']['Id']); } $filter = null; foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) { @@ -56,6 +56,7 @@ if ( !$filter ) { $filter = new ZM\Filter(); } +ZM\Debug('filter: ' . print_r($filter,true)); if ( isset($_REQUEST['filter']) ) { # Update our filter object with whatever changes we have made before saving $filter->set($_REQUEST['filter']); From 7b764d04d3a13f2f600868383a818291778594ff Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 17:40:31 -0500 Subject: [PATCH 165/169] Fix use of next when it should be return. Improve some logging of errors. --- scripts/zmtrigger.pl.in | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index be38c5e91..acd4ce255 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -372,9 +372,10 @@ sub handleMessage { Warning("Can't find monitor '$id' for message '$message'"); return; } - Debug("Found monitor for id '$id'"); - - next if !zmMemVerify($monitor); + if ( !zmMemVerify($monitor) ) { + Warning("Can't verify monitor '$id' for message '$message'"); + return; + } Debug("Handling action '$action'"); if ( $action =~ /^(enable|disable)(?:[\+ ](\d+))?$/ ) { @@ -393,12 +394,19 @@ sub handleMessage { handleDelay($delay, $connection, $action_text); } } elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) { - next if !$monitor->{Enabled}; + if ( !$monitor->{Enabled} ) { + Info('Motion detection not enabled on monitor '.$id); + return; + } my $trigger = $1; my $delay = $2; my $trigger_data; if ( $trigger eq 'on' ) { + if ( $score <= 0 ) { + Warning('Triggering on with invalid score will have no result.'); + return; + } zmTriggerEventOn($monitor, $score, $cause, $text); zmTriggerShowtext($monitor, $showtext) if defined($showtext); Info("Trigger '$trigger' '$cause'"); From 9636a76ccff7bbfdcc014ac3ef8ae1d28a25630a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 17:42:29 -0500 Subject: [PATCH 166/169] drop db lock before reporting mysql_errors --- src/zm_monitor.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 0acfb3ded..e2ea20f88 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1307,10 +1307,11 @@ bool Monitor::Analyse() { db_mutex.lock(); static char sql[ZM_SQL_SML_BUFSIZ]; snprintf(sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, fps, fps); - if ( mysql_query(&dbconn, sql) ) { - Error("Can't run query: %s", mysql_error(&dbconn)); - } + int rc = mysql_query(&dbconn, sql); db_mutex.unlock(); + if ( rc ) { + Error("Can't run query %s: %s", sql, mysql_error(&dbconn)); + } } // end if fps != new_fps last_fps_time = now.tv_sec; @@ -2583,11 +2584,11 @@ int Monitor::Capture() { "VALUES (%d, %.2lf, %u, 'Connected') ON DUPLICATE KEY UPDATE " "CaptureFPS = %.2lf, CaptureBandwidth=%u, Status='Connected'", id, fps, new_capture_bandwidth, fps, new_capture_bandwidth); - if ( mysql_query(&dbconn, sql) ) { - Error("Can't run query: %s", mysql_error(&dbconn)); - } + rc = mysql_query(&dbconn, sql); db_mutex.unlock(); - Debug(4,sql); + if ( rc ) { + Error("Can't run query %s: %s", sql, mysql_error(&dbconn)); + } } // end if time has changed since last update } // end if it might be time to report the fps } // end if captureResult From f91dcc9b6073041221b02cbd3c5fd6e04fd96f6e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 11 Nov 2020 20:05:47 -0500 Subject: [PATCH 167/169] declar rc as int --- src/zm_monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index e2ea20f88..d8e327eac 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2584,7 +2584,7 @@ int Monitor::Capture() { "VALUES (%d, %.2lf, %u, 'Connected') ON DUPLICATE KEY UPDATE " "CaptureFPS = %.2lf, CaptureBandwidth=%u, Status='Connected'", id, fps, new_capture_bandwidth, fps, new_capture_bandwidth); - rc = mysql_query(&dbconn, sql); + int rc = mysql_query(&dbconn, sql); db_mutex.unlock(); if ( rc ) { Error("Can't run query %s: %s", sql, mysql_error(&dbconn)); From 7faf774cd060964783458a384997db9d812ade20 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 12 Nov 2020 09:15:02 -0500 Subject: [PATCH 168/169] Use FriendsOfCake crud 3.2.0 --- distros/redhat/zoneminder.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index af62cefba..16904e725 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -3,7 +3,7 @@ %global zmgid_final apache # Crud is configured as a git submodule -%global crud_version 3.1.0-zm +%global crud_version 3.2.0 # CakePHP-Enum-Behavior is configured as a git submodule %global ceb_version 1.0-zm @@ -44,7 +44,7 @@ License: GPLv2+ and LGPLv2+ and MIT URL: http://www.zoneminder.com/ Source0: https://github.com/ZoneMinder/ZoneMinder/archive/%{version}.tar.gz#/zoneminder-%{version}.tar.gz -Source1: https://github.com/ZoneMinder/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz +Source1: https://github.com/FriendOfCake/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz Source2: https://github.com/ZoneMinder/CakePHP-Enum-Behavior/archive/%{ceb_version}.tar.gz#/cakephp-enum-behavior-%{ceb_version}.tar.gz %{?rhel:BuildRequires: epel-rpm-macros} From 645dca6bc92262883a23dceacf1621e5b5350026 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 12 Nov 2020 09:59:32 -0500 Subject: [PATCH 169/169] Use FriendsOfCake 3.2.0 Crud --- utils/packpack/startpackpack.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 1b2eafd8f..d464089d3 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -94,12 +94,12 @@ commonprep () { # The rpm specfile requires we download each submodule as a tarball then manually move it into place # Might as well do this for Debian as well, rather than git submodule init - CRUDVER="3.1.0-zm" + CRUDVER="3.2.0" if [ -e "build/crud-${CRUDVER}.tar.gz" ]; then echo "Found existing Crud ${CRUDVER} tarball..." else echo "Retrieving Crud ${CRUDVER} submodule..." - curl -L https://github.com/ZoneMinder/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz + curl -L https://github.com/FriendsOfCake/crud/archive/v${CRUDVER}.tar.gz > build/crud-${CRUDVER}.tar.gz if [ $? -ne 0 ]; then echo "ERROR: Crud tarball retreival failed..." exit 1