From 073dd34d656a475ffc66a24117ff88380d37edec Mon Sep 17 00:00:00 2001 From: Howard Date: Thu, 10 May 2018 20:59:08 -0700 Subject: [PATCH 01/23] fixed typo --- docs/userguide/viewmonitors.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/viewmonitors.rst b/docs/userguide/viewmonitors.rst index 1c67c4a25..448b63a9d 100644 --- a/docs/userguide/viewmonitors.rst +++ b/docs/userguide/viewmonitors.rst @@ -1,7 +1,7 @@ Viewing Monitors ================ -ZoneMinder allows you to view a live feed of your configured monitors. Once can access this view by clicking on the "Name" column of any of the monitors +ZoneMinder allows you to view a live feed of your configured monitors. One can access this view by clicking on the "Name" column of any of the monitors .. image:: images/viewmonitor-main.png :width: 500px From 6af74a96fc43700b7cdd13573862bb85b81a2e0c Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 13 May 2018 18:36:58 -0500 Subject: [PATCH 02/23] add fedora 28 to build system, remove fedora 26 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 78167f860..1ae0988d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,8 @@ env: - SMPFLAGS=-j4 matrix: - OS=el DIST=7 - - OS=fedora DIST=26 DOCKER_REPO=knnniggett/packpack - OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack + - OS=fedora DIST=28 DOCKER_REPO=knnniggett/packpack - OS=ubuntu DIST=trusty - OS=ubuntu DIST=xenial - OS=ubuntu DIST=trusty ARCH=i386 From 485f2929439a42903afc9b6c0624d2737d244ecf Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 14 May 2018 12:32:48 -0500 Subject: [PATCH 03/23] fix php 5.4 compatibility - remove calls to empty --- web/skins/classic/views/filter.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 26e1aa42e..675a178bf 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -346,17 +346,17 @@ echo htmlSelect( 'filter[Query][sort_asc]', $sort_dirns, $filter->sort_asc() );

- AutoArchive()) ) { ?> checked="checked" onclick="updateButtons( this )"/> + AutoArchive() ) { ?> checked="checked" onclick="updateButtons( this )"/>

- UpdateDiskSpace()) ? '' : ' checked="checked"' ?> onclick="updateButtons(this);"/> + UpdateDiskSpace() ? '' : ' checked="checked"' ?> onclick="updateButtons(this);"/>

- AutoVideo()) ) { ?> checked="checked" onclick="updateButtons( this )"/> + AutoVideo() ) { ?> checked="checked" onclick="updateButtons( this )"/>

- AutoUpload()) ) { ?> checked="checked" onclick="updateButtons( this )"/> + AutoUpload() ) { ?> checked="checked" onclick="updateButtons( this )"/>

- AutoEmail()) ) { ?> checked="checked" onclick="updateButtons( this )"/> + AutoEmail() ) { ?> checked="checked" onclick="updateButtons( this )"/>

- AutoMessage()) ) { ?> checked="checked" onclick="updateButtons( this )"/> + AutoMessage() ) { ?> checked="checked" onclick="updateButtons( this )"/>

- AutoExecute()) ) { ?> checked="checked"/> + AutoExecute() ) { ?> checked="checked"/>

- AutoDelete()) ) { ?> checked="checked" onclick="updateButtons(this)"/> + AutoDelete() ) { ?> checked="checked" onclick="updateButtons(this)"/>

- AutoMove()) ) { ?> checked="checked" onclick="updateButtons(this);if(this.checked){$j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');}else{this.form.elements['filter[AutoMoveTo]'].hide();};"/> + AutoMove() ) { ?> checked="checked" onclick="updateButtons(this);if(this.checked){$j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');}else{this.form.elements['filter[AutoMoveTo]'].hide();};"/> AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;' ) ); ?>

- Background()) ) { ?> checked="checked" onclick="updateButtons(this);"/> + Background() ) { ?> checked="checked" onclick="updateButtons(this);"/>

- Concurrent()) ) { ?> checked="checked" onclick="updateButtons(this);"/> + Concurrent() ) { ?> checked="checked" onclick="updateButtons(this);"/>


From 63e6cb1d6278bb5ff3c6d6f20b7c91eee151b9df Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 14 May 2018 13:56:55 -0400 Subject: [PATCH 04/23] remove parenthesis that confuse older php --- 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 b544f1526..de51b9876 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -20,7 +20,7 @@ public $defaults = array( 'limit' => 100, 'Query' => array(), 'sort_field' => ZM_WEB_EVENT_SORT_FIELD, - 'sort_asc' => (ZM_WEB_EVENT_SORT_ORDER == 'asc' ? 'asc' : 'desc'), + 'sort_asc' => ZM_WEB_EVENT_SORT_ORDER == 'asc' ? 'asc' : 'desc', ); public function __construct( $IdOrRow=NULL ) { From 038c5f4e1afa872b0946a8b14cb729752da6666e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 14 May 2018 13:57:26 -0400 Subject: [PATCH 05/23] log the log line not the uninitialized sql --- src/zm_logger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index ca17da92c..409736ca8 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -551,7 +551,7 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co } else { Level tempDatabaseLevel = mDatabaseLevel; databaseLevel(NOLOG); - Error("Can't insert log entry: sql(%s) error(db is locked)", sql); + Error("Can't insert log entry: sql(%s) error(db is locked)", logString); databaseLevel(tempDatabaseLevel); } } From 98b2a3f6f0d0829c4920f645fb130655fcdf7efc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 15 May 2018 12:44:24 -0400 Subject: [PATCH 06/23] improve structure/spacing --- src/zm_monitor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 4d8f65f7f..04c81492b 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1544,7 +1544,8 @@ bool Monitor::Analyse() { if ( score ) { if ( (state == IDLE || state == TAPE || state == PREALARM ) ) { if ( Event::PreAlarmCount() > alarm_frame_count ) { - Info( "%s: %03d - Gone into alarm state", name, image_count ); + Info("%s: %03d - Gone into alarm state %u > %u", + name, image_count, Event::PreAlarmCount(), alarm_frame_count); shared_data->state = state = ALARM; if ( signal_change || (function != MOCORD && state != ALERT) ) { int pre_index; From f16e1953d9d005844a082b875a6d0ac831b65dd4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 15 May 2018 10:45:10 -0700 Subject: [PATCH 07/23] Make Source filter apply to Path as well --- web/skins/classic/views/_monitor_filters.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/_monitor_filters.php b/web/skins/classic/views/_monitor_filters.php index c32cea01a..c0c6021d2 100644 --- a/web/skins/classic/views/_monitor_filters.php +++ b/web/skins/classic/views/_monitor_filters.php @@ -218,7 +218,9 @@ $html .= htmlSelect( 'Status[]', $status_options, $regexp = '/'.preg_quote($regexp,'/').'/i'; } if ( !preg_match($regexp, $Monitor->Source()) ) { - continue; + if ( !preg_match($regexp, $Monitor->Path()) ) { + continue; + } } } From 49d75ce03954a1ba3f953e16eae483ec4c2beb8f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 15 May 2018 10:45:47 -0700 Subject: [PATCH 08/23] handle Width and Height not being in ->{} and returnining defaults. Include Path in Source --- web/includes/Monitor.php | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index bde545594..9054cfebc 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -1,6 +1,6 @@ {$k} = $v; } if ( $this->{'Controllable'} ) { - $s = dbFetchOne( 'SELECT * FROM Controls WHERE Id=?', NULL, array( $this->{'ControlId'} ) ); + $s = dbFetchOne('SELECT * FROM Controls WHERE Id=?', NULL, array($this->{'ControlId'}) ); foreach ($s as $k => $v) { if ( $k == 'Id' ) { continue; @@ -165,13 +165,13 @@ private $control_fields = array( } } else { - Error('No row for Monitor ' . $IdOrRow ); + Error('No row for Monitor ' . $IdOrRow); } } # end if isset($IdOrRow) } // end function __construct public function Server() { - return new Server( $this->{'ServerId'} ); + return new Server($this->{'ServerId'}); } public function __call($fn, array $args){ if ( count($args) ) { @@ -240,18 +240,18 @@ private $control_fields = array( $this->{'Width'} = $new; if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) { - return $this->{'Height'}; + return array_key_exists('Height', $this) ? $this->{'Height'} : $this->defaults{'Height'}; } - return $this->{'Width'}; + return array_key_exists('Width',$this) ? $this->{'Width'} : $this->defaults{'Width'}; } public function Height( $new=null ) { if ( $new ) $this->{'Height'} = $new; if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) { - return $this->{'Width'}; + return array_key_exists('Width',$this) ? $this->{'Width'} : $this->defaults{'Width'}; } - return $this->{'Height'}; + return array_key_exists('Height', $this) ? $this->{'Height'} : $this->defaults{'Height'}; } public function set($data) { @@ -483,9 +483,9 @@ private $control_fields = array( $url_parts = parse_url( $this->{'Path'} ); unset($url_parts['user']); unset($url_parts['pass']); - unset($url_parts['scheme']); + #unset($url_parts['scheme']); unset($url_parts['query']); - unset($url_parts['path']); + #unset($url_parts['path']); if ( isset($url_parts['port']) and ( $url_parts['port'] == '80' or $url_parts['port'] == '554' ) ) unset($url_parts['port']); $source = unparse_url($url_parts); From 5df2fbfff2826fdde209ba0e6c85c6a9d0870bb8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 15 May 2018 15:53:25 -0400 Subject: [PATCH 09/23] fix logic to handle no pre_event frames --- 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 d9b07e40f..e8e14b3c4 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1543,7 +1543,7 @@ bool Monitor::Analyse() { } if ( score ) { if ( (state == IDLE || state == TAPE || state == PREALARM ) ) { - if ( Event::PreAlarmCount() > alarm_frame_count ) { + if ( (!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count) ) { Info("%s: %03d - Gone into alarm state %u > %u", name, image_count, Event::PreAlarmCount(), alarm_frame_count); shared_data->state = state = ALARM; From af63619ce62ad75acd56aaa628ef9bd615739866 Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 15 May 2018 21:56:17 +0200 Subject: [PATCH 10/23] Fix Messages=>Messaged --- web/includes/Event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Event.php b/web/includes/Event.php index bb89f541d..d7ce25dc4 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -27,7 +27,7 @@ class Event { 'Videoed', 'Uploaded', 'Emailed', -'Messages', +'Messaged', 'Executed', 'Notes', 'StateId', From 81c4542a94e57d82b6577106dd1ba000fa5d6611 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 16 May 2018 11:13:59 -0400 Subject: [PATCH 11/23] correct use of getValue. Use standard ddm element value instead --- web/skins/classic/views/js/controlpreset.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/web/skins/classic/views/js/controlpreset.js b/web/skins/classic/views/js/controlpreset.js index a59acaa64..979a63a85 100644 --- a/web/skins/classic/views/js/controlpreset.js +++ b/web/skins/classic/views/js/controlpreset.js @@ -1,10 +1,12 @@ function updateLabel() { - var presetIndex = $('contentForm').preset.getValue(); + var form = $('contentForm'); + var preset_ddm = form.elements['preset']; + + var presetIndex = preset_ddm[preset_ddm.selectedIndex].value; if ( labels[presetIndex] ) { - $('contentForm').newLabel.value = labels[presetIndex]; + form.newLabel.value = labels[presetIndex]; } else { - $('contentForm').newLabel.value = ""; + form.newLabel.value = ''; } } - -window.addEvent( 'domready', updateLabel ); +window.addEvent('domready', updateLabel); From 780cb693c25dcb5c42dd2b251ee7a33f5430e575 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 16 May 2018 11:14:11 -0400 Subject: [PATCH 12/23] google code style --- .../classic/includes/control_functions.php | 419 ++++++++---------- web/skins/classic/js/base.js | 2 +- web/skins/classic/views/controlpreset.php | 34 +- .../classic/views/js/controlpreset.js.php | 5 +- 4 files changed, 214 insertions(+), 246 deletions(-) diff --git a/web/skins/classic/includes/control_functions.php b/web/skins/classic/includes/control_functions.php index 4ce78dba4..7d4b7950e 100644 --- a/web/skins/classic/includes/control_functions.php +++ b/web/skins/classic/includes/control_functions.php @@ -18,126 +18,113 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -function getControlCommands( $monitor ) -{ - $cmds = array(); +function getControlCommands( $monitor ) { + $cmds = array(); - $cmds['Wake'] = "wake"; - $cmds['Sleep'] = "sleep"; - $cmds['Reset'] = "reset"; + $cmds['Wake'] = "wake"; + $cmds['Sleep'] = "sleep"; + $cmds['Reset'] = "reset"; - $cmds['PresetSet'] = "presetSet"; - $cmds['PresetGoto'] = "presetGoto"; - $cmds['PresetHome'] = "presetHome"; + $cmds['PresetSet'] = "presetSet"; + $cmds['PresetGoto'] = "presetGoto"; + $cmds['PresetHome'] = "presetHome"; - if ( $monitor->CanZoom() ) - { - if ( $monitor->CanZoomCon() ) - $cmds['ZoomRoot'] = "zoomCon"; - elseif ( $monitor->CanZoomRel() ) - $cmds['ZoomRoot'] = "zoomRel"; - elseif ( $monitor->CanZoomAbs() ) - $cmds['ZoomRoot'] = "zoomAbs"; - $cmds['ZoomTele'] = $cmds['ZoomRoot']."Tele"; - $cmds['ZoomWide'] = $cmds['ZoomRoot']."Wide"; - $cmds['ZoomStop'] = "zoomStop"; - $cmds['ZoomAuto'] = "zoomAuto"; - $cmds['ZoomMan'] = "zoomMan"; + if ( $monitor->CanZoom() ) { + if ( $monitor->CanZoomCon() ) + $cmds['ZoomRoot'] = "zoomCon"; + elseif ( $monitor->CanZoomRel() ) + $cmds['ZoomRoot'] = "zoomRel"; + elseif ( $monitor->CanZoomAbs() ) + $cmds['ZoomRoot'] = "zoomAbs"; + $cmds['ZoomTele'] = $cmds['ZoomRoot']."Tele"; + $cmds['ZoomWide'] = $cmds['ZoomRoot']."Wide"; + $cmds['ZoomStop'] = "zoomStop"; + $cmds['ZoomAuto'] = "zoomAuto"; + $cmds['ZoomMan'] = "zoomMan"; + } + + if ( $monitor->CanFocus() ) { + if ( $monitor->CanFocusCon() ) + $cmds['FocusRoot'] = "focusCon"; + elseif ( $monitor->CanFocusRel() ) + $cmds['FocusRoot'] = "focusRel"; + elseif ( $monitor->CanFocusAbs() ) + $cmds['FocusRoot'] = "focusAbs"; + $cmds['FocusFar'] = $cmds['FocusRoot']."Far"; + $cmds['FocusNear'] = $cmds['FocusRoot']."Near"; + $cmds['FocusStop'] = "focusStop"; + $cmds['FocusAuto'] = "focusAuto"; + $cmds['FocusMan'] = "focusMan"; + } + + if ( $monitor->CanIris() ) { + if ( $monitor->CanIrisCon() ) + $cmds['IrisRoot'] = "irisCon"; + elseif ( $monitor->CanIrisRel() ) + $cmds['IrisRoot'] = "irisRel"; + elseif ( $monitor->CanIrisAbs() ) + $cmds['IrisRoot'] = "irisAbs"; + $cmds['IrisOpen'] = $cmds['IrisRoot']."Open"; + $cmds['IrisClose'] = $cmds['IrisRoot']."Close"; + $cmds['IrisStop'] = "irisStop"; + $cmds['IrisAuto'] = "irisAuto"; + $cmds['IrisMan'] = "irisMan"; + } + + if ( $monitor->CanWhite() ) { + if ( $monitor->CanWhiteCon() ) + $cmds['WhiteRoot'] = "whiteCon"; + elseif ( $monitor->CanWhiteRel() ) + $cmds['WhiteRoot'] = "whiteRel"; + elseif ( $monitor->CanWhiteAbs() ) + $cmds['WhiteRoot'] = "whiteAbs"; + $cmds['WhiteIn'] = $cmds['WhiteRoot']."In"; + $cmds['WhiteOut'] = $cmds['WhiteRoot']."Out"; + $cmds['WhiteAuto'] = "whiteAuto"; + $cmds['WhiteMan'] = "whiteMan"; + } + + if ( $monitor->CanGain() ) { + if ( $monitor->CanGainCon() ) + $cmds['GainRoot'] = "gainCon"; + elseif ( $monitor->CanGainRel() ) + $cmds['GainRoot'] = "gainRel"; + elseif ( $monitor->CanGainAbs() ) + $cmds['GainRoot'] = "gainAbs"; + $cmds['GainUp'] = $cmds['GainRoot']."Up"; + $cmds['GainDown'] = $cmds['GainRoot']."Down"; + $cmds['GainAuto'] = "gainAuto"; + $cmds['GainMan'] = "gainMan"; + } + + if ( $monitor->CanMove() ) { + if ( $monitor->CanMoveCon() ) { + $cmds['MoveRoot'] = "moveCon"; + $cmds['Center'] = "moveStop"; + } elseif ( $monitor->CanMoveRel() ) { + $cmds['MoveRoot'] = "moveRel"; + $cmds['Center'] = $cmds['PresetHome']; + } elseif ( $monitor->CanMoveAbs() ) { + $cmds['MoveRoot'] = "moveAbs"; + $cmds['Center'] = $cmds['PresetHome']; + } else { + $cmds['MoveRoot'] = ''; } - if ( $monitor->CanFocus() ) - { - if ( $monitor->CanFocusCon() ) - $cmds['FocusRoot'] = "focusCon"; - elseif ( $monitor->CanFocusRel() ) - $cmds['FocusRoot'] = "focusRel"; - elseif ( $monitor->CanFocusAbs() ) - $cmds['FocusRoot'] = "focusAbs"; - $cmds['FocusFar'] = $cmds['FocusRoot']."Far"; - $cmds['FocusNear'] = $cmds['FocusRoot']."Near"; - $cmds['FocusStop'] = "focusStop"; - $cmds['FocusAuto'] = "focusAuto"; - $cmds['FocusMan'] = "focusMan"; - } - - if ( $monitor->CanIris() ) - { - if ( $monitor->CanIrisCon() ) - $cmds['IrisRoot'] = "irisCon"; - elseif ( $monitor->CanIrisRel() ) - $cmds['IrisRoot'] = "irisRel"; - elseif ( $monitor->CanIrisAbs() ) - $cmds['IrisRoot'] = "irisAbs"; - $cmds['IrisOpen'] = $cmds['IrisRoot']."Open"; - $cmds['IrisClose'] = $cmds['IrisRoot']."Close"; - $cmds['IrisStop'] = "irisStop"; - $cmds['IrisAuto'] = "irisAuto"; - $cmds['IrisMan'] = "irisMan"; - } - - if ( $monitor->CanWhite() ) - { - if ( $monitor->CanWhiteCon() ) - $cmds['WhiteRoot'] = "whiteCon"; - elseif ( $monitor->CanWhiteRel() ) - $cmds['WhiteRoot'] = "whiteRel"; - elseif ( $monitor->CanWhiteAbs() ) - $cmds['WhiteRoot'] = "whiteAbs"; - $cmds['WhiteIn'] = $cmds['WhiteRoot']."In"; - $cmds['WhiteOut'] = $cmds['WhiteRoot']."Out"; - $cmds['WhiteAuto'] = "whiteAuto"; - $cmds['WhiteMan'] = "whiteMan"; - } - - if ( $monitor->CanGain() ) - { - if ( $monitor->CanGainCon() ) - $cmds['GainRoot'] = "gainCon"; - elseif ( $monitor->CanGainRel() ) - $cmds['GainRoot'] = "gainRel"; - elseif ( $monitor->CanGainAbs() ) - $cmds['GainRoot'] = "gainAbs"; - $cmds['GainUp'] = $cmds['GainRoot']."Up"; - $cmds['GainDown'] = $cmds['GainRoot']."Down"; - $cmds['GainAuto'] = "gainAuto"; - $cmds['GainMan'] = "gainMan"; - } - - if ( $monitor->CanMove() ) - { - if ( $monitor->CanMoveCon() ) - { - $cmds['MoveRoot'] = "moveCon"; - $cmds['Center'] = "moveStop"; - } - elseif ( $monitor->CanMoveRel() ) - { - $cmds['MoveRoot'] = "moveRel"; - $cmds['Center'] = $cmds['PresetHome']; - } - elseif ( $monitor->CanMoveAbs() ) - { - $cmds['MoveRoot'] = "moveAbs"; - $cmds['Center'] = $cmds['PresetHome']; - } else { - $cmds['MoveRoot'] = ''; - } - - $cmds['MoveUp'] = $cmds['MoveRoot']."Up"; - $cmds['MoveDown'] = $cmds['MoveRoot']."Down"; - $cmds['MoveLeft'] = $cmds['MoveRoot']."Left"; - $cmds['MoveRight'] = $cmds['MoveRoot']."Right"; - $cmds['MoveUpLeft'] = $cmds['MoveRoot']."UpLeft"; - $cmds['MoveUpRight'] = $cmds['MoveRoot']."UpRight"; - $cmds['MoveDownLeft'] = $cmds['MoveRoot']."DownLeft"; - $cmds['MoveDownRight'] = $cmds['MoveRoot']."DownRight"; - } - return( $cmds ); + $cmds['MoveUp'] = $cmds['MoveRoot']."Up"; + $cmds['MoveDown'] = $cmds['MoveRoot']."Down"; + $cmds['MoveLeft'] = $cmds['MoveRoot']."Left"; + $cmds['MoveRight'] = $cmds['MoveRoot']."Right"; + $cmds['MoveUpLeft'] = $cmds['MoveRoot']."UpLeft"; + $cmds['MoveUpRight'] = $cmds['MoveRoot']."UpRight"; + $cmds['MoveDownLeft'] = $cmds['MoveRoot']."DownLeft"; + $cmds['MoveDownRight'] = $cmds['MoveRoot']."DownRight"; + } + return( $cmds ); } -function controlFocus( $monitor, $cmds ) -{ - ob_start(); +function controlFocus( $monitor, $cmds ) { + ob_start(); ?>
@@ -146,24 +133,22 @@ function controlFocus( $monitor, $cmds )
CanAutoFocus() ) - { + if ( $monitor->CanAutoFocus() ) { ?>
@@ -172,23 +157,21 @@ function controlZoom( $monitor, $cmds )
CanAutoZoom() ) - { + if ( $monitor->CanAutoZoom() ) { ?>
@@ -197,24 +180,22 @@ function controlIris( $monitor, $cmds )
CanAutoIris() ) - { + if ( $monitor->CanAutoIris() ) { ?>
@@ -223,170 +204,158 @@ function controlWhite( $monitor, $cmds )
CanAutoWhite() ) - { + if ( $monitor->CanAutoWhite() ) { ?>
CanPan(); - $hasTilt = $monitor->CanTilt(); - $hasDiag = $hasPan && $hasTilt && $monitor->CanMoveDiag(); + $hasPan = $monitor->CanPan(); + $hasTilt = $monitor->CanTilt(); + $hasDiag = $hasPan && $hasTilt && $monitor->CanMoveDiag(); ?> -
-
-
-
+
+
+
+
-
+
-
+
-
-
-
-
+
+
+
+
Id() ) ) as $row ) - { - $labels[$row['Preset']] = $row['Label']; - } + $sql = 'SELECT * FROM ControlPresets WHERE MonitorId = ?'; + $labels = array(); + foreach( dbFetchAll( $sql, NULL, array( $monitor->Id() ) ) as $row ) { + $labels[$row['Preset']] = $row['Label']; + } - $presetBreak = (int)(($monitor->NumPresets()+1)/((int)(($monitor->NumPresets()-1)/MAX_PRESETS)+1)); + $presetBreak = (int)(($monitor->NumPresets()+1)/((int)(($monitor->NumPresets()-1)/MAX_PRESETS)+1)); - ob_start(); + ob_start(); ?>
NumPresets(); $i++ ) - { -?>" value="" onclick="controlCmd('');"/>NumPresets(); $i++ ) { + ?> + " value="" onclick="controlCmd('');"/> +
HasHomePreset() ) - { + if ( $monitor->HasHomePreset() ) { ?> CanSetPresets() ) - { + } + if ( canEdit('Monitors') && $monitor->CanSetPresets() ) { ?> - +
CanWake() ) - { + if ( $monitor->CanWake() ) { ?> CanSleep() ) - { + } + if ( $monitor->CanSleep() ) { ?> CanReset() ) - { + } + if ( $monitor->CanReset() ) { ?>
-
+
CanFocus() ) - echo controlFocus( $monitor, $cmds ); - if ( $monitor->CanZoom() ) - echo controlZoom( $monitor, $cmds ); - if ( $monitor->CanIris() ) - echo controlIris( $monitor, $cmds ); - if ( $monitor->CanWhite() ) - echo controlWhite( $monitor, $cmds ); - if ( $monitor->CanMove() ) { + if ( $monitor->CanFocus() ) + echo controlFocus($monitor, $cmds); + if ( $monitor->CanZoom() ) + echo controlZoom($monitor, $cmds); + if ( $monitor->CanIris() ) + echo controlIris($monitor, $cmds); + if ( $monitor->CanWhite() ) + echo controlWhite($monitor, $cmds); + if ( $monitor->CanMove() ) { ?> -
+
+ +
CanWake() || $monitor->CanSleep() || $monitor->CanReset() ) + echo controlPower($monitor, $cmds); + if ( $monitor->HasPresets() ) + echo controlPresets($monitor, $cmds); ?> -
+
CanWake() || $monitor->CanSleep() || $monitor->CanReset() ) - echo controlPower( $monitor, $cmds ); - if ( $monitor->HasPresets() ) - echo controlPresets( $monitor, $cmds ); -?> -
- diff --git a/web/skins/classic/js/base.js b/web/skins/classic/js/base.js index f4684833e..b19ca29a0 100644 --- a/web/skins/classic/js/base.js +++ b/web/skins/classic/js/base.js @@ -56,7 +56,7 @@ var popupSizes = { 'onvifprobe': { 'width': 700, 'height': 550 }, 'optionhelp': { 'width': 400, 'height': 320 }, 'options': { 'width': 1000, 'height': 660 }, - 'preset': { 'width': 300, 'height': 120 }, + 'preset': { 'width': 300, 'height': 220 }, 'server': { 'width': 600, 'height': 405 }, 'settings': { 'width': 220, 'height': 235 }, 'state': { 'width': 400, 'height': 170 }, diff --git a/web/skins/classic/views/controlpreset.php b/web/skins/classic/views/controlpreset.php index 23fec060e..0de2a85e2 100644 --- a/web/skins/classic/views/controlpreset.php +++ b/web/skins/classic/views/controlpreset.php @@ -18,30 +18,26 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canEdit( 'Monitors' ) ) -{ - $view = "error"; - return; +if ( !canEdit('Monitors') ) { + $view = 'error'; + return; } -$monitor = dbFetchOne( 'SELECT C.*,M.* FROM Monitors AS M INNER JOIN Controls AS C ON (M.ControlId = C.Id ) WHERE M.Id = ?', NULL, array( $_REQUEST['mid']) ); +$monitor = dbFetchOne('SELECT C.*,M.* FROM Monitors AS M INNER JOIN Controls AS C ON (M.ControlId = C.Id ) WHERE M.Id = ?', NULL, array( $_REQUEST['mid']) ); $labels = array(); foreach( dbFetchAll( 'SELECT * FROM ControlPresets WHERE MonitorId = ?', NULL, array( $monitor['Id'] ) ) as $row ) { - $labels[$row['Preset']] = $row['Label']; + $labels[$row['Preset']] = $row['Label']; } $presets = array(); -for ( $i = 1; $i <= $monitor['NumPresets']; $i++ ) -{ - $presets[$i] = translate('Preset')." ".$i; - if ( !empty($labels[$i]) ) - { - $presets[$i] .= " (".validHtmlStr($labels[$i]).")"; - } +for ( $i = 1; $i <= $monitor['NumPresets']; $i++ ) { + $presets[$i] = translate('Preset').' '.$i; + if ( !empty($labels[$i]) ) { + $presets[$i] .= ' ('.validHtmlStr($labels[$i]).')'; + } } - $focusWindow = true; xhtmlHeaders(__FILE__, translate('SetPreset') ); @@ -58,10 +54,14 @@ xhtmlHeaders(__FILE__, translate('SetPreset') ); -

-

+

+

+ + +

- + +
diff --git a/web/skins/classic/views/js/controlpreset.js.php b/web/skins/classic/views/js/controlpreset.js.php index ea8b31fa6..d358b3369 100644 --- a/web/skins/classic/views/js/controlpreset.js.php +++ b/web/skins/classic/views/js/controlpreset.js.php @@ -1,9 +1,8 @@ var labels = new Array(); $label ) -{ +foreach ( $labels as $index=>$label ) { ?> -labels[] = ""; +labels[] = ''; From 93dd943fec326001437ca1615b915bfb6e673911 Mon Sep 17 00:00:00 2001 From: Isaac Date: Wed, 16 May 2018 20:17:57 +0200 Subject: [PATCH 13/23] Fix some spacing --- web/api/app/Plugin/Crud | 2 +- web/skins/classic/views/js/log.js | 13 +-- web/skins/classic/views/log.php | 165 +++++++++++++++--------------- 3 files changed, 89 insertions(+), 91 deletions(-) diff --git a/web/api/app/Plugin/Crud b/web/api/app/Plugin/Crud index 0bd63fb46..c3976f147 160000 --- a/web/api/app/Plugin/Crud +++ b/web/api/app/Plugin/Crud @@ -1 +1 @@ -Subproject commit 0bd63fb464957080ead342db58ca9e01532cf1ef +Subproject commit c3976f1478c681b0bbc132ec3a3e82c3984eeed5 diff --git a/web/skins/classic/views/js/log.js b/web/skins/classic/views/js/log.js index 2e5990af6..8af30cf25 100644 --- a/web/skins/classic/views/js/log.js +++ b/web/skins/classic/views/js/log.js @@ -34,7 +34,7 @@ function buildFetchParms( parms ) { fetchParms += '&filter['+key+']='+value; } ); - return( fetchParms ); + return fetchParms; } function fetchNextLogs() { @@ -247,6 +247,7 @@ function updateFilterSelectors() { } if ( filter[key] ) selector.set('value', filter[key]); + } ); } @@ -257,11 +258,11 @@ function initPage() { logCodes[''+i] = 'DB'+i; logTable = new HtmlTable( $('logTable'), { -zebra: true, -sortable: true, -sortReverse: true -} -); + zebra: true, + sortable: true, + sortReverse: true + } + ); logTable.addEvent( 'sort', function( tbody, index ) { var header = tbody.getParent( 'table' ).getElement( 'thead' ); var columns = header.getElement( 'tr' ).getElements( 'th' ); diff --git a/web/skins/classic/views/log.php b/web/skins/classic/views/log.php index 260915672..0b33fe860 100644 --- a/web/skins/classic/views/log.php +++ b/web/skins/classic/views/log.php @@ -18,10 +18,9 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'System' ) ) -{ - $view = "error"; - return; +if ( !canView('System') ) { + $view = 'error'; + return; } $focusWindow = true; @@ -31,92 +30,90 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
-
- -
+
+
+
- - - - - - - - - - - - -
- - - - - - - - -
- - - - - - - - -
- -
-
- - - - - - - - - - - - - - - - -
-
-
-
+ + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + +
+
+
+
+
From 25703fb2d4ff985de6a011b5b7f22208920d9750 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 18 May 2018 09:03:01 -0400 Subject: [PATCH 14/23] Speed up log query response by generating the options out of the log rows instead of hitting the db again. --- web/ajax/log.php | 809 ++++++++++++++++++++++------------------------- 1 file changed, 385 insertions(+), 424 deletions(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index ac9b62ad6..14fc1d772 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -4,443 +4,404 @@ # These are the valid columns that you can filter on. $filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' ); -switch ( $_REQUEST['task'] ) -{ - case 'create' : - { - // Silently ignore bogus requests - if ( !empty($_POST['level']) && !empty($_POST['message']) ) - { - logInit( array( 'id' => "web_js" ) ); +switch ( $_REQUEST['task'] ) { + case 'create' : + { + // Silently ignore bogus requests + if ( !empty($_POST['level']) && !empty($_POST['message']) ) { + 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 = $_POST['line']; - else - $line = NULL; + $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/\w+\//', '', $_POST['file'] ) : ''; + if ( !empty( $_POST['line'] ) ) + $line = $_POST['line']; + else + $line = NULL; - $levels = array_flip(Logger::$codes); - if ( !isset($levels[$_POST['level']]) ) - Panic( "Unexpected logger level '".$_POST['level']."'" ); - $level = $levels[$_POST['level']]; - Logger::fetch()->logPrint( $level, $string, $file, $line ); - } - ajaxResponse(); - break; + $levels = array_flip(Logger::$codes); + if ( !isset($levels[$_POST['level']]) ) + Panic("Unexpected logger level '".$_POST['level']."'"); + $level = $levels[$_POST['level']]; + Logger::fetch()->logPrint( $level, $string, $file, $line ); } - case 'query' : - { - if ( !canView( 'System' ) ) - ajaxError( 'Insufficient permissions to view log entries' ); + ajaxResponse(); + break; + } + case 'query' : + { + if ( !canView('System') ) + ajaxError('Insufficient permissions to view log entries'); - $servers = Server::find_all(); - $servers_by_Id = array(); -# There is probably a better way to do this. - foreach ( $servers as $server ) { - $servers_by_Id[$server->Id()] = $server; - } - - $minTime = isset($_REQUEST['minTime'])?$_REQUEST['minTime']:NULL; - $maxTime = isset($_REQUEST['maxTime'])?$_REQUEST['maxTime']:NULL; - - $limit = 100; - if ( isset($_REQUEST['limit']) ) { - if ( ( !is_integer( $_REQUEST['limit'] ) and !ctype_digit($_REQUEST['limit']) ) ) { - Error("Invalid value for limit " . $_REQUEST['limit'] ); - } else { - $limit = $_REQUEST['limit']; - } - } - $sortField = 'TimeKey'; - if ( isset($_REQUEST['sortField']) ) { - if ( ! in_array( $_REQUEST['sortField'], $filterFields ) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) { - Error("Invalid sort field " . $_REQUEST['sortField'] ); - } else { - $sortField = $_REQUEST['sortField']; - } - } - $sortOrder = (isset($_REQUEST['sortOrder']) and $_REQUEST['sortOrder']) == 'asc' ? 'asc':'desc'; - $filter = isset($_REQUEST['filter'])?$_REQUEST['filter']:array(); - - $total = dbFetchOne( 'SELECT count(*) AS Total FROM Logs', 'Total' ); - $sql = 'SELECT * FROM Logs'; - $where = array(); - $values = array(); - if ( $minTime ) { - $where[] = "TimeKey > ?"; - $values[] = $minTime; - } elseif ( $maxTime ) { - $where[] = "TimeKey < ?"; - $values[] = $maxTime; - } - - foreach ( $filter as $field=>$value ) { - if ( ! in_array( $field, $filterFields ) ) { - Error("$field is not in valid filter fields"); - continue; - } - if ( $field == 'Level' ){ - $where[] = $field." <= ?"; - $values[] = $value; - } else { - $where[] = $field." = ?"; - $values[] = $value; - } - } - if ( count($where) ) - $sql.= ' WHERE '.join( ' AND ', $where ); - $sql .= " order by ".$sortField." ".$sortOrder." limit ".$limit; - $logs = array(); - foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) { - $log['DateTime'] = preg_replace( '/^\d+/', strftime( '%Y-%m-%d %H:%M:%S', intval($log['TimeKey']) ), $log['TimeKey'] ); - $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; - $log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message'] ); - $logs[] = $log; - } - $options = array(); - $where = array(); - $values = array(); - foreach( $filter as $field=>$value ) { - if ( $field == 'Level' ) { - $where[$field] = $field." <= ?"; - $values[$field] = $value; - } else { - $where[$field] = $field." = ?"; - $values[$field] = $value; - } - } - foreach( $filterFields as $field ) - { - $sql = "SELECT DISTINCT $field FROM Logs WHERE NOT isnull($field)"; - $fieldWhere = array_diff_key( $where, array( $field=>true ) ); - $fieldValues = array_diff_key( $values, array( $field=>true ) ); - if ( count($fieldWhere) ) - $sql.= " AND ".join( ' AND ', $fieldWhere ); - $sql.= " ORDER BY $field ASC"; - if ( $field == 'Level' ) - { - foreach( dbFetchAll( $sql, $field, array_values($fieldValues) ) as $value ) - if ( $value <= Logger::INFO ) - $options[$field][$value] = Logger::$codes[$value]; - else - $options[$field][$value] = "DB".$value; - } - elseif ( $field == 'ServerId' ) - { - foreach( dbFetchAll( $sql, $field, array_values($fieldValues) ) as $value ) - $options['ServerId'][$value] = ( $value and isset($servers_by_Id[$value]) ) ? $servers_by_Id[$value]->Name() : ''; - - } - else - { - foreach( dbFetchAll( $sql, $field, array_values( $fieldValues ) ) as $value ) - if ( $value != '' ) - $options[$field][] = $value; - } - } - if ( count($filter) ) - { - $sql = "SELECT count(*) AS Available FROM Logs WHERE ".join( ' AND ', $where ); - $available = dbFetchOne( $sql, 'Available', array_values($values) ); - } - ajaxResponse( array( - 'updated' => preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG ), - 'total' => $total, - 'available' => isset($available)?$available:$total, - 'logs' => $logs, - 'state' => logState(), - 'options' => $options - ) ); - break; + $servers = Server::find_all(); + $servers_by_Id = array(); + # There is probably a better way to do this. + foreach ( $servers as $server ) { + $servers_by_Id[$server->Id()] = $server; } - case 'export' : + + $minTime = isset($_REQUEST['minTime'])?$_REQUEST['minTime']:NULL; + $maxTime = isset($_REQUEST['maxTime'])?$_REQUEST['maxTime']:NULL; + + $limit = 100; + if ( isset($_REQUEST['limit']) ) { + if ( ( !is_integer( $_REQUEST['limit'] ) and !ctype_digit($_REQUEST['limit']) ) ) { + Error('Invalid value for limit ' . $_REQUEST['limit'] ); + } else { + $limit = $_REQUEST['limit']; + } + } + $sortField = 'TimeKey'; + if ( isset($_REQUEST['sortField']) ) { + if ( ! in_array( $_REQUEST['sortField'], $filterFields ) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) { + Error("Invalid sort field " . $_REQUEST['sortField'] ); + } else { + $sortField = $_REQUEST['sortField']; + } + } + $sortOrder = (isset($_REQUEST['sortOrder']) and $_REQUEST['sortOrder']) == 'asc' ? 'asc':'desc'; + $filter = isset($_REQUEST['filter'])?$_REQUEST['filter']:array(); + + $total = dbFetchOne('SELECT count(*) AS Total FROM Logs', 'Total'); + $sql = 'SELECT * FROM Logs'; + $where = array(); + $values = array(); + if ( $minTime ) { + $where[] = 'TimeKey > ?'; + $values[] = $minTime; + } elseif ( $maxTime ) { + $where[] = 'TimeKey < ?'; + $values[] = $maxTime; + } + + foreach ( $filter as $field=>$value ) { + if ( ! in_array($field, $filterFields) ) { + Error("$field is not in valid filter fields"); + continue; + } + if ( $field == 'Level' ){ + $where[] = $field.' <= ?'; + $values[] = $value; + } else { + $where[] = $field.' = ?'; + $values[] = $value; + } + } + $options = array(); + if ( count($where) ) + $sql.= ' WHERE '.join( ' AND ', $where ); + $sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit; + $logs = array(); + foreach ( dbFetchAll($sql, NULL, $values) as $log ) { + $log['DateTime'] = preg_replace('/^\d+/', strftime('%Y-%m-%d %H:%M:%S', intval($log['TimeKey'])), $log['TimeKey']); + $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; + $log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message'] ); + foreach( $filterFields as $field ) { + if ( ! isset( $options[$field] ) ) + $options[$field] = array(); + $value = $log[$field]; + + if ( $field == 'Level' ) { + if ( $value <= Logger::INFO ) + $options[$field][$value] = Logger::$codes[$value]; + else + $options[$field][$value] = 'DB'.$value; + } else if ( $field == 'ServerId' ) { + $options['ServerId'][$value] = ( $value and isset($servers_by_Id[$value]) ) ? $servers_by_Id[$value]->Name() : ''; + } else if ( isset($log[$field]) ) { + $options[$field][$log[$field]] = $log[$field]; + } + } + $logs[] = $log; + } + + $available = count($logs); + ajaxResponse( array( + 'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG)?strftime(DATE_FMT_CONSOLE_LONG):date(DATE_FMT_CONSOLE_LONG), + 'total' => $total, + 'available' => isset($available)?$available:$total, + 'logs' => $logs, + 'state' => logState(), + 'options' => $options + ) ); + break; + } + case 'export' : + { + if ( !canView('System') ) + ajaxError('Insufficient permissions to export logs'); + + $minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL; + $maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL; + if ( !is_null($minTime) && !is_null($maxTime) && $minTime > $maxTime ) { + $tempTime = $minTime; + $minTime = $maxTime; + $maxTime = $tempTime; + } + //$limit = isset($_POST['limit'])?$_POST['limit']:1000; + $filter = isset($_POST['filter'])?$_POST['filter']:array(); + $sortField = 'TimeKey'; + if ( isset($_POST['sortField']) ) { + if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) { + Error("Invalid sort field " . $_POST['sortField'] ); + } else { + $sortField = $_POST['sortField']; + } + } + $sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc'; + + $servers = Server::find_all(); + $servers_by_Id = array(); + # There is probably a better way to do this. + foreach ( $servers as $server ) { + $servers_by_Id[$server->Id()] = $server; + } + + $sql = 'SELECT * FROM Logs'; + $where = array(); + $values = array(); + if ( $minTime ) { + preg_match('/(.+)(\.\d+)/', $minTime, $matches); + $minTime = strtotime($matches[1]).$matches[2]; + $where[] = 'TimeKey >= ?'; + $values[] = $minTime; + } + if ( $maxTime ) { + preg_match('/(.+)(\.\d+)/', $maxTime, $matches); + $maxTime = strtotime($matches[1]).$matches[2]; + $where[] = 'TimeKey <= ?'; + $values[] = $maxTime; + } + foreach ( $filter as $field=>$value ) { + if ( $value != '' ) { + if ( $field == 'Level' ) { + $where[] = $field.' <= ?'; + $values[] = $value; + } else { + $where[] = $field.' = ?'; + $values[] = $value; + } + } + } + if ( count($where) ) + $sql.= ' WHERE '.join( ' AND ', $where ); + $sql .= ' ORDER BY '.$sortField.' '.$sortOrder; + //$sql .= " limit ".dbEscape($limit); + $format = isset($_POST['format'])?$_POST['format']:'text'; + switch( $format ) { + case 'text' : + $exportExt = 'txt'; + break; + case 'tsv' : + $exportExt = 'tsv'; + break; + case 'html' : + $exportExt = 'html'; + break; + case 'xml' : + $exportExt = 'xml'; + break; + default : + Fatal("Unrecognised log export format '$format'"); + } + $exportKey = substr(md5(rand()),0,8); + $exportFile = "zm-log.$exportExt"; + $exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt"; + if ( !($exportFP = fopen( $exportPath, "w" )) ) + Fatal("Unable to open log export file $exportPath"); + $logs = array(); + foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) { + $log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] ); + $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; + $logs[] = $log; + } + switch( $format ) { + case 'text' : { - if ( !canView( 'System' ) ) - ajaxError( 'Insufficient permissions to export logs' ); - - $minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL; - $maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL; - if ( !is_null($minTime) && !is_null($maxTime) && $minTime > $maxTime ) - { - $tempTime = $minTime; - $minTime = $maxTime; - $maxTime = $tempTime; - } - //$limit = isset($_POST['limit'])?$_POST['limit']:1000; - $filter = isset($_POST['filter'])?$_POST['filter']:array(); - $sortField = 'TimeKey'; - if ( isset($_POST['sortField']) ) { - if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) { - Error("Invalid sort field " . $_POST['sortField'] ); - } else { - $sortField = $_POST['sortField']; - } - } - $sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc'; - - $servers = Server::find_all(); - $servers_by_Id = array(); - # There is probably a better way to do this. - foreach ( $servers as $server ) { - $servers_by_Id[$server->Id()] = $server; - } - - $sql = "select * from Logs"; - $where = array(); - $values = array(); - if ( $minTime ) - { - preg_match( '/(.+)(\.\d+)/', $minTime, $matches ); - $minTime = strtotime($matches[1]).$matches[2]; - $where[] = "TimeKey >= ?"; - $values[] = $minTime; - } - if ( $maxTime ) - { - preg_match( '/(.+)(\.\d+)/', $maxTime, $matches ); - $maxTime = strtotime($matches[1]).$matches[2]; - $where[] = "TimeKey <= ?"; - $values[] = $maxTime; - } - foreach ( $filter as $field=>$value ) { - if ( $value != '' ) { - if ( $field == 'Level' ) { - $where[] = $field." <= ?"; - $values[] = $value; - } else { - $where[] = $field." = ?'"; - $values[] = $value; - } - } - } - if ( count($where) ) - $sql.= " where ".join( " and ", $where ); - $sql .= " order by ".$sortField." ".$sortOrder; - //$sql .= " limit ".dbEscape($limit); - $format = isset($_POST['format'])?$_POST['format']:'text'; - switch( $format ) - { - case 'text' : - $exportExt = "txt"; - break; - case 'tsv' : - $exportExt = "tsv"; - break; - case 'html' : - $exportExt = "html"; - break; - case 'xml' : - $exportExt = "xml"; - break; - default : - Fatal( "Unrecognised log export format '$format'" ); - } - $exportKey = substr(md5(rand()),0,8); - $exportFile = "zm-log.$exportExt"; - $exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt"; - if ( !($exportFP = fopen( $exportPath, "w" )) ) - Fatal( "Unable to open log export file $exportPath" ); - $logs = array(); - foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) - { - $log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] ); - $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; - $logs[] = $log; - } - switch( $format ) - { - case 'text' : - { - foreach ( $logs as $log ) - { - if ( $log['Line'] ) - fprintf( $exportFP, "%s %s[%d].%s-%s/%d [%s]\n", $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Line'], $log['Message'] ); - else - fprintf( $exportFP, "%s %s[%d].%s-%s [%s]\n", $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Message'] ); - } - break; - } - case 'tsv' : - { -# This line doesn't need fprintf, it could use fwrite - fprintf( $exportFP, join( "\t", - translate('DateTime'), - translate('Component'), - translate('Server'), - translate('Pid'), - translate('Level'), - translate('Message'), - translate('File'), - translate('Line') - )."\n" ); - foreach ( $logs as $log ) - { - fprintf( $exportFP, "%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); - } - break; - } - case 'html' : - { - fwrite( $exportFP, -' - - - '.translate('ZoneMinderLog').' - - - + foreach ( $logs as $log ) { + if ( $log['Line'] ) + fprintf( $exportFP, "%s %s[%d].%s-%s/%d [%s]\n", + $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Line'], $log['Message'] ); + else + fprintf( $exportFP, "%s %s[%d].%s-%s [%s]\n", + $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Message'] ); + } + break; + } + case 'tsv' : + { + # This line doesn't need fprintf, it could use fwrite + fprintf( $exportFP, join( "\t", + translate('DateTime'), + translate('Component'), + translate('Server'), + translate('Pid'), + translate('Level'), + translate('Message'), + translate('File'), + translate('Line') + )."\n" ); + foreach ( $logs as $log ) { + fprintf( $exportFP, "%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); + } + break; + } + case 'html' : + { + fwrite( $exportFP, + ' + + + + '.translate('ZoneMinderLog').' + + +

'.translate('ZoneMinderLog').'

'.htmlspecialchars(preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG )).'

'.count($logs).' '.translate('Logs').'

- - -' ); - foreach ( $logs as $log ) - { - $classLevel = $log['Level']; - if ( $classLevel < Logger::FATAL ) - $classLevel = Logger::FATAL; - elseif ( $classLevel > Logger::DEBUG ) - $classLevel = Logger::DEBUG; - $logClass = 'log-'.strtolower(Logger::$codes[$classLevel]); - fprintf( $exportFP, " \n", $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); - } - fwrite( $exportFP, -' -
'.translate('DateTime').''.translate('Component').''.translate('Server').''.translate('Pid').''.translate('Level').''.translate('Message').''.translate('File').''.translate('Line').'
%s%s%s%d%s%s%s%s
- -' ); - break; - } - case 'xml' : - { - fwrite( $exportFP, -' - - '.$_POST['selector'].'' ); - foreach ( $filter as $field=>$value ) - if ( $value != '' ) - fwrite( $exportFP, -' - <'.strtolower($field).'>'.htmlspecialchars($value).' - ' ); - fwrite( $exportFP, -' - '.translate('DateTime').''.translate('Component').''.translate('Pid').''.translate('Level').''.translate('Message').''.translate('File').''.translate('Line').' - - -' ); - foreach ( $logs as $log ) - { - fprintf( $exportFP, -" - %s - %s - %s - %d - %s - - %s - %d - \n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] ); - } - fwrite( $exportFP, -' -' ); - break; - } - $exportExt = "xml"; - break; - } - fclose( $exportFP ); - ajaxResponse( array( - 'key' => $exportKey, - 'format' => $format, - ) ); - break; + + '.translate('DateTime').''.translate('Component').''.translate('Server').''.translate('Pid').''.translate('Level').''.translate('Message').''.translate('File').''.translate('Line').' + ' ); + foreach ( $logs as $log ) { + $classLevel = $log['Level']; + if ( $classLevel < Logger::FATAL ) + $classLevel = Logger::FATAL; + elseif ( $classLevel > Logger::DEBUG ) + $classLevel = Logger::DEBUG; + $logClass = 'log-'.strtolower(Logger::$codes[$classLevel]); + fprintf( $exportFP, " %s%s%s%d%s%s%s%s\n", $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); } - case 'download' : + fwrite( $exportFP, + ' + + + ' ); + break; + } + case 'xml' : { - if ( !canView( 'System' ) ) - ajaxError( 'Insufficient permissions to download logs' ); - - if ( empty($_REQUEST['key']) ) - Fatal( "No log export key given" ); - $exportKey = $_REQUEST['key']; - if ( empty($_REQUEST['format']) ) - Fatal( "No log export format given" ); - $format = $_REQUEST['format']; - - switch( $format ) - { - case 'text' : - $exportExt = "txt"; - break; - case 'tsv' : - $exportExt = "tsv"; - break; - case 'html' : - $exportExt = "html"; - break; - case 'xml' : - $exportExt = "xml"; - break; - default : - Fatal( "Unrecognised log export format '$format'" ); - } - - $exportFile = "zm-log.$exportExt"; - $exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt"; - - header( "Pragma: public" ); - header( "Expires: 0" ); - header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" ); - header( "Cache-Control: private", false ); // required by certain browsers - header( "Content-Description: File Transfer" ); - header( 'Content-Disposition: attachment; filename="'.$exportFile.'"' ); - header( "Content-Transfer-Encoding: binary" ); - header( "Content-Type: application/force-download" ); - header( "Content-Length: ".filesize($exportPath) ); - readfile( $exportPath ); - exit( 0 ); - break; + fwrite( $exportFP, + ' + + '.$_POST['selector'].'' ); + foreach ( $filter as $field=>$value ) + if ( $value != '' ) + fwrite( $exportFP, + ' + <'.strtolower($field).'>'.htmlspecialchars($value).' + ' ); + fwrite( $exportFP, + ' + '.translate('DateTime').''.translate('Component').''.translate('Pid').''.translate('Level').''.translate('Message').''.translate('File').''.translate('Line').' + + + ' ); + foreach ( $logs as $log ) { + fprintf( $exportFP, + " + %s + %s + %s + %d + %s + + %s + %d + \n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] ); + } + fwrite( $exportFP, + ' + ' ); + break; } + $exportExt = "xml"; + break; + } + fclose( $exportFP ); + ajaxResponse( array( + 'key' => $exportKey, + 'format' => $format, + ) ); + break; + } + case 'download' : + { + if ( !canView('System') ) + ajaxError('Insufficient permissions to download logs'); + + if ( empty($_REQUEST['key']) ) + Fatal( "No log export key given" ); + $exportKey = $_REQUEST['key']; + if ( empty($_REQUEST['format']) ) + Fatal( "No log export format given" ); + $format = $_REQUEST['format']; + + switch( $format ) { + case 'text' : + $exportExt = 'txt'; + break; + case 'tsv' : + $exportExt = 'tsv'; + break; + case 'html' : + $exportExt = 'html'; + break; + case 'xml' : + $exportExt = 'xml'; + break; + default : + Fatal("Unrecognised log export format '$format'"); + } + + $exportFile = "zm-log.$exportExt"; + $exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt"; + + header( "Pragma: public" ); + header( "Expires: 0" ); + header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" ); + header( "Cache-Control: private", false ); // required by certain browsers + header( "Content-Description: File Transfer" ); + header( 'Content-Disposition: attachment; filename="'.$exportFile.'"' ); + header( "Content-Transfer-Encoding: binary" ); + header( "Content-Type: application/force-download" ); + header( "Content-Length: ".filesize($exportPath) ); + readfile( $exportPath ); + exit( 0 ); + break; + } } - -ajaxError( 'Unrecognised action or insufficient permissions' ); - +ajaxError('Unrecognised action or insufficient permissions'); ?> From 8276386a442f71adffe0860057eb46765268bdf7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 18 May 2018 09:04:47 -0400 Subject: [PATCH 15/23] We always return an associative array now --- web/api/app/Plugin/Crud | 2 +- web/skins/classic/views/js/log.js | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/web/api/app/Plugin/Crud b/web/api/app/Plugin/Crud index c3976f147..0bd63fb46 160000 --- a/web/api/app/Plugin/Crud +++ b/web/api/app/Plugin/Crud @@ -1 +1 @@ -Subproject commit c3976f1478c681b0bbc132ec3a3e82c3984eeed5 +Subproject commit 0bd63fb464957080ead342db58ca9e01532cf1ef diff --git a/web/skins/classic/views/js/log.js b/web/skins/classic/views/js/log.js index 8af30cf25..1353b7796 100644 --- a/web/skins/classic/views/js/log.js +++ b/web/skins/classic/views/js/log.js @@ -229,21 +229,22 @@ function updateFilterSelectors() { if ( key == 'Level' ) { Object.each(values, function( value, label ) { - selector.options[selector.options.length] = new Option( value, label ); + selector.options[selector.options.length] = new Option(value, label); } ); } else if ( key == 'ServerId' ) { Object.each(values, function( value, label ) { - selector.options[selector.options.length] = new Option( value, label ); + selector.options[selector.options.length] = new Option(value, label); } ); } else { - values.each( - function( value ) { - selector.options[selector.options.length] = new Option( value ); + Object.each(values, + function( value, label ) { + selector.options[selector.options.length] = new Option(value, label); } ); + } } if ( filter[key] ) selector.set('value', filter[key]); From 4815162beaf742e5ceed7aa24a510f52ee73982e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 18 May 2018 09:10:29 -0400 Subject: [PATCH 16/23] fix extra } --- web/skins/classic/views/js/log.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/skins/classic/views/js/log.js b/web/skins/classic/views/js/log.js index 1353b7796..0d1d0b3be 100644 --- a/web/skins/classic/views/js/log.js +++ b/web/skins/classic/views/js/log.js @@ -244,7 +244,6 @@ function updateFilterSelectors() { selector.options[selector.options.length] = new Option(value, label); } ); - } } if ( filter[key] ) selector.set('value', filter[key]); From 2a8ea98249ccd5ba90f0e92f1c573f1a0eab209a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 18 May 2018 09:12:10 -0400 Subject: [PATCH 17/23] remove blank space at end of line --- web/skins/classic/views/log.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/web/skins/classic/views/log.php b/web/skins/classic/views/log.php index 0b33fe860..4f2650865 100644 --- a/web/skins/classic/views/log.php +++ b/web/skins/classic/views/log.php @@ -31,7 +31,7 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
- + From cc27ce7ee9b2c1d789707ae6e70db32a1aec326d Mon Sep 17 00:00:00 2001 From: Isaac Date: Fri, 18 May 2018 15:50:45 +0200 Subject: [PATCH 18/23] Turn off csrf for archive downloading, which prevents out of memeory --- web/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/index.php b/web/index.php index 44c751352..d93b46e23 100644 --- a/web/index.php +++ b/web/index.php @@ -200,7 +200,7 @@ isset($view) || $view = NULL; isset($request) || $request = NULL; isset($action) || $action = NULL; -if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames') { +if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames' && $view != 'archive' ) { require_once( 'includes/csrf/csrf-magic.php' ); #Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); csrf_check(); From cfbbc238c973774d6093f1d37df446a9033764d7 Mon Sep 17 00:00:00 2001 From: Isaac Date: Fri, 18 May 2018 15:51:12 +0200 Subject: [PATCH 19/23] remove extra spaces and parenthesis --- web/skins/classic/includes/export_functions.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/web/skins/classic/includes/export_functions.php b/web/skins/classic/includes/export_functions.php index 5d23b1125..879fd82c9 100644 --- a/web/skins/classic/includes/export_functions.php +++ b/web/skins/classic/includes/export_functions.php @@ -732,11 +732,6 @@ function loadintoIframe(iframeid, url){ return( ob_get_clean() ); } - - - - - function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc ) { if ( (!canView('Events')) or ! $eid ) { @@ -816,7 +811,7 @@ function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exp } $files = array(); } - return( array_values( $exportFileList ) ); + return array_values($exportFileList); } function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat, $exportStructure = false ) { @@ -900,5 +895,5 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo unlink($monitorPath.'/'.$html_eventMaster); } - return( '?view=archive%26type='.$exportFormat ); + return '?view=archive%26type='.$exportFormat; } From d8a62e0edea3157a5fa6c495459ff07b8e06aba6 Mon Sep 17 00:00:00 2001 From: Isaac Date: Fri, 18 May 2018 15:51:42 +0200 Subject: [PATCH 20/23] Show total size for non-montage review downloads as well --- web/skins/classic/views/download.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/download.php b/web/skins/classic/views/download.php index d9e8bf7e3..06142799c 100644 --- a/web/skins/classic/views/download.php +++ b/web/skins/classic/views/download.php @@ -66,7 +66,10 @@ if ( !empty($_REQUEST['eid']) ) { $Event = new Event( $_REQUEST['eid'] ); echo 'Downloading event ' . $_REQUEST['eid'] . ' Resulting file should be approximately ' . human_filesize( $Event->DiskSpace() ); } else if ( !empty($_REQUEST['eids']) ) { + $total_size = 0; foreach ( $_REQUEST['eids'] as $eid ) { + $Event = new Event($eid); + $total_size += $Event->DiskSpace(); ?> There are no events found. Resulting download will be empty.'; + echo '
There are no events found. Resulting download will be empty.
'; } ?>
- + - + - +
- + - + - +
From 7ad6b0131011fdda57333231d92ce0de47fdcc54 Mon Sep 17 00:00:00 2001 From: Isaac Date: Fri, 18 May 2018 15:52:12 +0200 Subject: [PATCH 21/23] double to single quotes and spacing --- web/skins/classic/views/js/download.js.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/download.js.php b/web/skins/classic/views/js/download.js.php index cc4bbb83f..8e47bd2f6 100644 --- a/web/skins/classic/views/js/download.js.php +++ b/web/skins/classic/views/js/download.js.php @@ -2,9 +2,9 @@ if ( isset($_REQUEST['eids']) ) { $eidParms = array(); foreach ( $_REQUEST['eids'] as $eid ) - $eidParms[] = "eids[]=".validInt($eid); + $eidParms[] = 'eids[]='.validInt($eid); ?> -var eidParm = ''; +var eidParm = ''; From 337db8bb18a107034f283e92edd989d54bbffb07 Mon Sep 17 00:00:00 2001 From: Isaac Date: Fri, 18 May 2018 15:52:30 +0200 Subject: [PATCH 22/23] Include Content-Length so we get a download progress --- web/views/archive.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/web/views/archive.php b/web/views/archive.php index 9238a925e..017c1f0a7 100644 --- a/web/views/archive.php +++ b/web/views/archive.php @@ -18,7 +18,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'Events' ) ) { +if ( !canView('Events') ) { $view = 'error'; return; } @@ -43,11 +43,15 @@ if ( $archivetype ) { if ( $mimetype ) { $filename = "zmExport.$file_ext"; $filename_path = ZM_DIR_EXPORTS.'/'.$filename; + Logger::Debug("downloading archive from $filename_path"); if ( is_readable($filename_path) ) { - header( "Content-type: application/$mimetype" ); - header( "Content-Disposition: attachment; filename=$filename"); + header("Content-type: application/$mimetype" ); + header("Content-Disposition: inline; filename=$filename"); + header('Content-Length: ' . filesize($filename_path) ); set_time_limit(0); - readfile( $filename_path ); + if ( ! @readfile( $filename_path ) ) { + Error("Error sending $filename_path"); + } } else { Error("$filename_path does not exist or is not readable."); } From 77b144a13e191614f6ac5036338119947e29213b Mon Sep 17 00:00:00 2001 From: Isaac Date: Fri, 18 May 2018 16:07:58 +0200 Subject: [PATCH 23/23] must specify type=button or else some browsers treat it as a submit button --- web/skins/classic/views/export.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/web/skins/classic/views/export.php b/web/skins/classic/views/export.php index 029e7e487..54fad211c 100644 --- a/web/skins/classic/views/export.php +++ b/web/skins/classic/views/export.php @@ -18,7 +18,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'Events' ) ) { +if ( !canView('Events') ) { $view = 'error'; return; } @@ -53,16 +53,12 @@ xhtmlHeaders(__FILE__, translate('Export') );
-
+
@@ -101,7 +97,7 @@ elseif ( !empty($_REQUEST['eids']) )
- +