diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index d1614007e..ae755bdd0 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -3035,7 +3035,7 @@ our @options = ( }, { name => 'ZM_WEB_H_REFRESH_NAVBAR', - default => '5', + default => '60', description => 'How often (in seconds) the navigation header should refresh itself', help => q` The navigation header contains the general status information about server load and storage space. @@ -3308,7 +3308,7 @@ our @options = ( }, { name => 'ZM_WEB_M_REFRESH_NAVBAR', - default => '15', + default => '120', description => 'How often (in seconds) the navigation header should refresh itself', help => q` The navigation header contains the general status information about server load and storage space. @@ -3581,7 +3581,7 @@ our @options = ( }, { name => 'ZM_WEB_L_REFRESH_NAVBAR', - default => '35', + default => '180', description => 'How often (in seconds) the navigation header should refresh itself', help => q` The navigation header contains the general status information about server load and storage space. diff --git a/web/ajax/log.php b/web/ajax/log.php index 282303a87..2a5aa039e 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -15,7 +15,7 @@ switch ( $_REQUEST['task'] ) { $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : ''; if ( !empty( $_POST['line'] ) ) - $line = $_POST['line']; + $line = validInt($_POST['line']); else $line = NULL; diff --git a/web/includes/Frame.php b/web/includes/Frame.php index 74a18ef59..d4c2a4dee 100644 --- a/web/includes/Frame.php +++ b/web/includes/Frame.php @@ -50,9 +50,8 @@ class Frame { } public function getImageSrc( $show='capture' ) { - - return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'FrameId'}.'&eid='.$this->{'EventId'}.'&show='.$show; - #return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg'; + return '?view=image&fid='.$this->{'FrameId'}.'&eid='.$this->{'EventId'}.'&show='.$show; + #return '?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg'; } // end function getImageSrc public static function find( $parameters = array(), $options = NULL ) { diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index fecdcab46..87a374845 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -331,6 +331,20 @@ private $control_fields = array( return $this->defaults{$field}; } // end function Height + public function SignalCheckColour($new=null) { + $field = 'SignalCheckColour'; + if ($new) { + $this->{$field} = $new; + } + + // Validate that it's a valid colour (we seem to allow color names, not just hex). + // This also helps prevent XSS. + if (array_key_exists($field, $this) && preg_match('/^[#0-9a-zA-Z]+$/', $this->{$field})) { + return $this->{$field}; + } + return $this->defaults{$field}; + } // end function SignalCheckColour + public function set($data) { foreach ($data as $k => $v) { if ( method_exists($this, $k) ) { diff --git a/web/includes/Server.php b/web/includes/Server.php index 65721214d..ea633c4be 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -117,7 +117,8 @@ class Server { if ( isset($this->{'PathToIndex'}) and $this->{'PathToIndex'} ) { return $this->{'PathToIndex'}; } - return $_SERVER['PHP_SELF']; + // We can't trust PHP_SELF to not include an XSS vector. See note in skin.js.php. + return preg_replace('/\.php.*$/i', '.php', $_SERVER['PHP_SELF']); } public function UrlToIndex( $port=null ) { diff --git a/web/includes/actions/groups.php b/web/includes/actions/groups.php index 200f65f99..22d138240 100644 --- a/web/includes/actions/groups.php +++ b/web/includes/actions/groups.php @@ -43,7 +43,7 @@ if ( $action == 'delete' ) { $Group->delete(); } } - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=groups'; + $redirect = '?view=groups'; $refreshParent = true; } # end if action ?> diff --git a/web/includes/actions/montage.php b/web/includes/actions/montage.php index 7182ba2dc..3040fd83a 100644 --- a/web/includes/actions/montage.php +++ b/web/includes/actions/montage.php @@ -40,7 +40,7 @@ if ( isset($_REQUEST['object']) ) { $_SESSION['zmMontageLayout'] = $Layout->Id(); setcookie('zmMontageLayout', $Layout->Id(), 1); session_write_close(); - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montage'; + $redirect = '?view=montage'; } // end if save } # end if isset($_REQUEST['object'] ) diff --git a/web/includes/actions/options.php b/web/includes/actions/options.php index 263a592f8..d7853ec9e 100644 --- a/web/includes/actions/options.php +++ b/web/includes/actions/options.php @@ -89,7 +89,7 @@ if ( $action == 'delete' ) { case 'lowband' : break; } - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=options&tab='.$_REQUEST['tab']; + $redirect = '?view=options&tab='.$_REQUEST['tab']; } loadConfig(false); return; diff --git a/web/includes/actions/privacy.php b/web/includes/actions/privacy.php index 19c4061ea..99bbd7150 100644 --- a/web/includes/actions/privacy.php +++ b/web/includes/actions/privacy.php @@ -28,12 +28,12 @@ if ( ($action == 'privacy') && isset($_REQUEST['option']) ) { case 'decline' : dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'"); dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_TELEMETRY_DATA'"); - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; + $redirect = '?view=console'; break; case 'accept' : dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'"); dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_TELEMETRY_DATA'"); - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; + $redirect = '?view=console'; break; default: # Enable the privacy statement if we somehow submit something other than accept or decline dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_SHOW_PRIVACY'"); diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php index 692015e70..584432ef7 100644 --- a/web/includes/csrf/csrf-magic.php +++ b/web/includes/csrf/csrf-magic.php @@ -288,9 +288,13 @@ function csrf_callback($tokens) { echo "CSRF check failed

CSRF check failed. Your form session may have expired, or you may not have - cookies enabled.

-
$data
-

Debug: $tokens

+ cookies enabled.

"; + if (ZM_LOG_DEBUG) { + // Don't make it too easy for users to inflict a CSRF attack on themselves. + echo "

Only try again if you weren't sent to this page by someone as this is potentially a sign of an attack.

"; + echo "
$data
"; + } + echo "

Debug: $tokens

"; } diff --git a/web/includes/functions.php b/web/includes/functions.php index 8b490bbde..e5917caf1 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -53,7 +53,11 @@ function CSPHeaders($view, $nonce) { case 'controlcap': case 'cycle': case 'donate': + case 'download': case 'error': + case 'events': + case 'export': + case 'frame': case 'function': case 'log': case 'logout': @@ -290,7 +294,7 @@ function getImageStreamHTML( $id, $src, $width, $height, $title='' ) { function outputControlStream( $src, $width, $height, $monitor, $scale, $target ) { ?> -
+ @@ -360,7 +364,7 @@ function getWebSiteUrl( $id, $src, $width, $height, $title='' ) { function outputControlStill( $src, $width, $height, $monitor, $scale, $target ) { ?> - + @@ -494,7 +498,6 @@ function makePopupButton( $url, $winName, $winSize, $buttonValue, $condition=1, } function htmlSelect( $name, $contents, $values, $behaviours=false ) { - $behaviourText = ''; if ( !empty($behaviours) ) { if ( is_array($behaviours) ) { @@ -532,10 +535,10 @@ function htmlOptions($contents, $values) { $text = $option; } $selected = is_array($values) ? in_array($value, $values) : !strcmp($value, $values); - $options_html .= ""; + ">".htmlspecialchars($text, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false).""; } return $options_html; } @@ -610,7 +613,7 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) { { if ( is_array($newValues[$key]) ) { if ( (!isset($values[$key])) or ( join(',',$newValues[$key]) != $values[$key] ) ) { - $changes[$key] = "`$key` = ".dbEscape(join(',',$newValues[$key])); + $changes[$key] = "`$key` = '".dbEscape(join(',',$newValues[$key]))."'"; } } else if ( (!isset($values[$key])) or $values[$key] ) { $changes[$key] = "`$key` = ''"; @@ -1083,7 +1086,7 @@ function parseSort( $saveToSession=false, $querySep='&' ) { $_SESSION['sort_asc'] = validHtmlStr($_REQUEST['sort_asc']); } if ($_REQUEST['limit'] != '') { - $limitQuery = "&limit=".$_REQUEST['limit']; + $limitQuery = "&limit=".validInt($_REQUEST['limit']); } } @@ -1424,7 +1427,7 @@ function getPagination( $pages, $page, $maxShortcuts, $query, $querySep='&' function sortHeader( $field, $querySep='&' ) { global $view; - return( '?view='.$view.$querySep.'page=1'.$_REQUEST['filter']['query'].$querySep.'sort_field='.$field.$querySep.'sort_asc='.($_REQUEST['sort_field'] == $field?!$_REQUEST['sort_asc']:0).$querySep.'limit='.$_REQUEST['limit'] ); + return '?view='.$view.$querySep.'page=1'.$_REQUEST['filter']['query'].$querySep.'sort_field='.$field.$querySep.'sort_asc='.($_REQUEST['sort_field'] == $field?!$_REQUEST['sort_asc']:0).$querySep.'limit='.validInt($_REQUEST['limit']); } function sortTag( $field ) { diff --git a/web/includes/logger.php b/web/includes/logger.php index 8bc81fb97..28d0ce902 100644 --- a/web/includes/logger.php +++ b/web/includes/logger.php @@ -455,7 +455,10 @@ function Error( $string ) { function Fatal( $string ) { Logger::fetch()->logPrint( Logger::FATAL, $string ); - die( htmlentities($string) ); + if (Logger::fetch()->debugOn()) { + echo(htmlentities($string)); + } + exit(1); } function Panic( $string ) { @@ -474,7 +477,10 @@ function Panic( $string ) { } } Logger::fetch()->logPrint( Logger::PANIC, $string.$backtrace ); - die( $string ); + if (Logger::fetch()->debugOn()) { + echo $string; + } + exit(1); } function ErrorHandler( $error, $string, $file, $line ) { diff --git a/web/index.php b/web/index.php index 4f9cb2dd2..eb9062a91 100644 --- a/web/index.php +++ b/web/index.php @@ -217,8 +217,9 @@ if ( ZM_OPT_USE_AUTH and !isset($user) and ($view != 'login') ) { $view = 'none'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login'; $request = null; -} else if ( ZM_SHOW_PRIVACY && ($action != 'privacy') && ($view != 'options') && (!$request) && canEdit('System') ) { +} else if ( ZM_SHOW_PRIVACY && ($view != 'privacy') && ($view != 'options') && (!$request) && canEdit('System') ) { $view = 'none'; + Logger::Debug('Redirecting to privacy'); $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=privacy'; $request = null; } diff --git a/web/skins/classic/css/base/views/frame.css b/web/skins/classic/css/base/views/frame.css index c9cb1846c..947fee1bc 100644 --- a/web/skins/classic/css/base/views/frame.css +++ b/web/skins/classic/css/base/views/frame.css @@ -9,8 +9,3 @@ display: flex; justify-content: space-between; } - -#controls a { - width: 40px; - margin-left: -20px; -} diff --git a/web/skins/classic/css/classic/views/frame.css b/web/skins/classic/css/classic/views/frame.css index c9cb1846c..947fee1bc 100644 --- a/web/skins/classic/css/classic/views/frame.css +++ b/web/skins/classic/css/classic/views/frame.css @@ -9,8 +9,3 @@ display: flex; justify-content: space-between; } - -#controls a { - width: 40px; - margin-left: -20px; -} diff --git a/web/skins/classic/css/dark/views/frame.css b/web/skins/classic/css/dark/views/frame.css index c9cb1846c..947fee1bc 100644 --- a/web/skins/classic/css/dark/views/frame.css +++ b/web/skins/classic/css/dark/views/frame.css @@ -9,8 +9,3 @@ display: flex; justify-content: space-between; } - -#controls a { - width: 40px; - margin-left: -20px; -} diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 703cd49d3..063977942 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -57,7 +57,7 @@ function xhtmlHeaders( $file, $title ) { - <?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?> + <?php echo validHtmlStr(ZM_WEB_TITLE_PREFIX); ?> - <?php echo validHtmlStr($title) ?> @@ -254,7 +254,7 @@ function getNavBarHTML($reload = null) { - + ; var navBarRefresh = ; var currentView = ''; -var thisUrl = ''; + +var thisUrl = ''; var skinPath = ''; var serverId = ''; diff --git a/web/skins/classic/views/_monitor_filters.php b/web/skins/classic/views/_monitor_filters.php index 0f94a2546..0656773f1 100644 --- a/web/skins/classic/views/_monitor_filters.php +++ b/web/skins/classic/views/_monitor_filters.php @@ -95,7 +95,7 @@ if ( ! empty($user['MonitorIds']) ) { } $html .= ''; -$html .= ''; +$html .= ''; $html .= ''; $Functions = array(); @@ -160,7 +160,7 @@ $html .= htmlSelect( 'Status[]', $status_options, $html .= ''; $html .= ''; - $html .= ''; + $html .= ''; $html .= ''; $sql = 'SELECT *,S.Status AS Status, S.CaptureFPS AS CaptureFPS, S.AnalysisFPS AS AnalysisFPS, S.CaptureBandwidth AS CaptureBandwidth diff --git a/web/skins/classic/views/add_monitors.php b/web/skins/classic/views/add_monitors.php index 98eb87b16..403c643c9 100644 --- a/web/skins/classic/views/add_monitors.php +++ b/web/skins/classic/views/add_monitors.php @@ -33,7 +33,7 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
- +
Results diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index aa909700e..da583853d 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -160,7 +160,7 @@ if ( $show_storage_areas ) $left_columns += 1; xhtmlHeaders( __FILE__, translate('Console') ); getBodyTopHTML(); ?> - + @@ -280,7 +280,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) { $Groups = $Group->Parents(); array_push( $Groups, $Group ); } - return implode(' > ', array_map(function($Group){ return ''.$Group->Name().''; }, $Groups )); + return implode(' > ', array_map(function($Group){ return ''.$Group->Name().''; }, $Groups )); }, $Monitor->GroupIds() ) ); ?>
@@ -308,7 +308,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) { Name(); ?> '. makePopupLink( '?view=monitor&mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', ''.$Monitor->Source().'', canEdit('Monitors') ).''; + echo ''. makePopupLink( '?view=monitor&mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', ''.validHtmlStr($Monitor->Source()).'', canEdit('Monitors') ).''; if ( $show_storage_areas ) { ?> Name(); } ?> diff --git a/web/skins/classic/views/control.php b/web/skins/classic/views/control.php index c40740bca..0b52641ea 100644 --- a/web/skins/classic/views/control.php +++ b/web/skins/classic/views/control.php @@ -60,7 +60,7 @@ xhtmlHeaders(__FILE__, translate('Control') );

- + diff --git a/web/skins/classic/views/controlcap.php b/web/skins/classic/views/controlcap.php index 7fdf2844a..546c27a93 100644 --- a/web/skins/classic/views/controlcap.php +++ b/web/skins/classic/views/controlcap.php @@ -183,7 +183,7 @@ foreach ( $tabs as $name=>$value ) ?>
-
+ diff --git a/web/skins/classic/views/controlcaps.php b/web/skins/classic/views/controlcaps.php index 6ba3065dc..3ae021f9b 100644 --- a/web/skins/classic/views/controlcaps.php +++ b/web/skins/classic/views/controlcaps.php @@ -39,7 +39,7 @@ xhtmlHeaders(__FILE__, translate('ControlCaps') );

- + diff --git a/web/skins/classic/views/controlpreset.php b/web/skins/classic/views/controlpreset.php index 22b89fea1..1862d071c 100644 --- a/web/skins/classic/views/controlpreset.php +++ b/web/skins/classic/views/controlpreset.php @@ -48,7 +48,7 @@ xhtmlHeaders(__FILE__, translate('SetPreset') );

- + diff --git a/web/skins/classic/views/device.php b/web/skins/classic/views/device.php index d9ea940fa..fa1a6a9d4 100644 --- a/web/skins/classic/views/device.php +++ b/web/skins/classic/views/device.php @@ -41,7 +41,7 @@ xhtmlHeaders( __FILE__, translate('Device')." - ".$newDevice['Name'] );

- + diff --git a/web/skins/classic/views/devices.php b/web/skins/classic/views/devices.php index bfeb8cfb3..783d7775a 100644 --- a/web/skins/classic/views/devices.php +++ b/web/skins/classic/views/devices.php @@ -40,7 +40,7 @@ xhtmlHeaders(__FILE__, translate('Devices') );

- + diff --git a/web/skins/classic/views/donate.php b/web/skins/classic/views/donate.php index 6eb0bc202..b18e2b010 100644 --- a/web/skins/classic/views/donate.php +++ b/web/skins/classic/views/donate.php @@ -45,7 +45,7 @@ xhtmlHeaders(__FILE__, translate('Donate') );

ZoneMinder -

- +

diff --git a/web/skins/classic/views/download.php b/web/skins/classic/views/download.php index 14ff51998..0b8d02fc2 100644 --- a/web/skins/classic/views/download.php +++ b/web/skins/classic/views/download.php @@ -45,6 +45,23 @@ if (isset($_SESSION['montageReviewFilter']) and !isset($_REQUEST['eids']) ) { #Logger::Debug("NO montageReviewFilter"); } +$exportFormat = ''; +if (isset($_REQUEST['exportFormat'])) { + if (!in_array($_REQUEST['exportFormat'], array('zip', 'tar'))) { + Error('Invalid exportFormat'); + return; + } + $exportFormat = $_REQUEST['exportFormat']; +} + +if (!empty($_REQUEST['eid'])) { + $Event = new Event( $_REQUEST['eid'] ); + if (!$Event->Id) { + Error('Invalid event id'); + return; + } +} + $focusWindow = true; $connkey = isset($_REQUEST['connkey']) ? $_REQUEST['connkey'] : generateConnKey(); @@ -67,7 +84,7 @@ if ( !empty($_REQUEST['eid']) ) { DiskSpace() ); + echo 'Downloading event ' . $Event->Id . '. Resulting file should be approximately ' . human_filesize( $Event->DiskSpace() ); } else if ( !empty($_REQUEST['eids']) ) { $total_size = 0; foreach ( $_REQUEST['eids'] as $eid ) { @@ -95,9 +112,9 @@ if ( !empty($_REQUEST['eid']) ) {

@@ -126,7 +143,7 @@ if ( !empty($_REQUEST['eid']) ) { } if ( !empty($_REQUEST['generated']) ) { ?> - + diff --git a/web/skins/classic/views/eventdetail.php b/web/skins/classic/views/eventdetail.php index 2e959d445..35f4eec30 100644 --- a/web/skins/classic/views/eventdetail.php +++ b/web/skins/classic/views/eventdetail.php @@ -74,7 +74,7 @@ if ( $mode == 'single' ) { ?>
- +

- +
- +
diff --git a/web/skins/classic/views/export.php b/web/skins/classic/views/export.php index 5d761b37c..4229f5437 100644 --- a/web/skins/classic/views/export.php +++ b/web/skins/classic/views/export.php @@ -47,6 +47,13 @@ if ( isset($_SESSION['export']) ) { $_REQUEST['exportCompress'] = 0; } +if (isset($_REQUEST['exportFormat'])) { + if (!in_array($_REQUEST['exportFormat'], array('zip', 'tar'))) { + Error('Invalid exportFormat'); + return; + } +} + $focusWindow = true; $connkey = isset($_REQUEST['connkey']) ? $_REQUEST['connkey'] : generateConnKey(); @@ -205,7 +212,7 @@ while ( $event_row = dbFetchNext($results) ) {
- + - +
- +
-
+
@@ -188,7 +188,7 @@ if ( (null !== $filter->Concurrent()) and $filter->Concurrent() )

- +

@@ -281,13 +281,13 @@ for ( $i=0; $i < count($terms); $i++ ) { } else { ?> - + - + @@ -385,7 +385,7 @@ if ( ZM_OPT_MESSAGE ) {

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

diff --git a/web/skins/classic/views/frame.php b/web/skins/classic/views/frame.php index 931951056..ae69fecba 100644 --- a/web/skins/classic/views/frame.php +++ b/web/skins/classic/views/frame.php @@ -51,14 +51,15 @@ $lastFid = $maxFid; $alarmFrame = $Frame->Type()=='Alarm'; if ( isset( $_REQUEST['scale'] ) ) { - $scale = $_REQUEST['scale']; + $scale = validNum($_REQUEST['scale']); } else if ( isset( $_COOKIE['zmWatchScale'.$Monitor->Id()] ) ) { - $scale = $_COOKIE['zmWatchScale'.$Monitor->Id()]; + $scale = validNum($_COOKIE['zmWatchScale'.$Monitor->Id()]); } else if ( isset( $_COOKIE['zmWatchScale'] ) ) { - $scale = $_COOKIE['zmWatchScale']; + $scale = validNum($_COOKIE['zmWatchScale']); } else { $scale = max( reScale( SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); } +$scale = $scale ?: "auto"; $imageData = $Event->getImageSrc( $frame, $scale, 0 ); if ( ! $imageData ) { @@ -67,7 +68,7 @@ if ( ! $imageData ) { } $show = 'capt'; -if ( isset($_REQUEST['show']) ) { +if (isset($_REQUEST['show']) && in_array($_REQUEST['show'], array('capt', 'anal'))) { $show = $_REQUEST['show']; } else if ( $imageData['hasAnalImage'] ) { $show = 'anal'; @@ -89,9 +90,9 @@ xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id()." - ".$Frame->Frame

Id().'&fid='.$Frame->FrameId(), 'zmStats', 'stats', translate('Stats') ); } ?> - +
-
+

Id().'-'.$Frame->FrameId().' ('.$Frame->Score().')' ?>

@@ -103,19 +104,19 @@ xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id()." - ".$Frame->Frame ', $Event->Id(), $Frame->FrameId(), $scale, ( $show=='anal'?'capt':'anal' ) ); } ?> -<?php echo $Frame->EventId().FrameId() ?>" class=""/> +<?php echo $Frame->EventId().FrameId() ?>" class=""/>

FrameId() > 1 ) { ?> - - + + FrameId() < $maxFid ) { ?> - - + +

diff --git a/web/skins/classic/views/frames.php b/web/skins/classic/views/frames.php index bd8fc6bfd..83e3f69dd 100644 --- a/web/skins/classic/views/frames.php +++ b/web/skins/classic/views/frames.php @@ -39,7 +39,7 @@ xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id() );

- Id() ?>

- +
diff --git a/web/skins/classic/views/function.php b/web/skins/classic/views/function.php index e92c2ed0c..506bc006b 100644 --- a/web/skins/classic/views/function.php +++ b/web/skins/classic/views/function.php @@ -35,7 +35,7 @@ xhtmlHeaders(__FILE__, translate('Function').' - '.validHtmlStr($monitor['Name']

- + diff --git a/web/skins/classic/views/group.php b/web/skins/classic/views/group.php index 9ccbd112c..ac689a176 100644 --- a/web/skins/classic/views/group.php +++ b/web/skins/classic/views/group.php @@ -34,10 +34,10 @@ xhtmlHeaders(__FILE__, translate('Group').' - '.$newGroup->Name());
- +
diff --git a/web/skins/classic/views/groups.php b/web/skins/classic/views/groups.php index a1cfec231..9a6bf9242 100644 --- a/web/skins/classic/views/groups.php +++ b/web/skins/classic/views/groups.php @@ -47,7 +47,7 @@ xhtmlHeaders(__FILE__, translate('Groups'));
- +
diff --git a/web/skins/classic/views/js/download.js b/web/skins/classic/views/js/download.js index 76ff7d17d..0c25431c0 100644 --- a/web/skins/classic/views/js/download.js +++ b/web/skins/classic/views/js/download.js @@ -29,7 +29,7 @@ function exportProgress() { } function exportResponse( respObj, respText ) { - window.location.replace( thisUrl+'?view='+currentView+'&'+eidParm+'&exportFile='+respObj.exportFile+'&generated='+((respObj.result=='Ok')?1:0) ); + window.location.replace( thisUrl+'?view='+currentView+'&'+eidParm+'&exportFormat='+respObj.exportFormat+'&generated='+((respObj.result=='Ok')?1:0) ); } function exportEvent( form ) { @@ -48,6 +48,9 @@ function initPage() { if ( exportReady ) { startDownload.pass( exportFile ).delay( 1500 ); } + document.getElementById('exportButton').addEventListener("click", function onClick(evt) { + exportEvent(this.form); + }); } window.addEventListener( 'DOMContentLoaded', initPage ); diff --git a/web/skins/classic/views/js/download.js.php b/web/skins/classic/views/js/download.js.php index 8e47bd2f6..3501fc711 100644 --- a/web/skins/classic/views/js/download.js.php +++ b/web/skins/classic/views/js/download.js.php @@ -14,6 +14,6 @@ var eidParm = 'eid='; ?> var exportReady = ; -var exportFile = ''; +var exportFile = '?view=archive&type='; var exportProgressString = ''; diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js index 37e4092f9..8a3fa9354 100644 --- a/web/skins/classic/views/js/events.js +++ b/web/skins/classic/views/js/events.js @@ -167,12 +167,20 @@ function initPage() { if ( window.history.length == 1 ) { $j('#controls').children().eq(0).html(''); } - $j('.colThumbnail img').each(function(){ - this.addEventListener('mouseover',thumbnail_onmouseover,false); - this.addEventListener('mouseout',thumbnail_onmouseout,false); + $j('.colThumbnail img').each(function() { + this.addEventListener('mouseover', thumbnail_onmouseover, false); + this.addEventListener('mouseout', thumbnail_onmouseout, false); }); - $j('input[name=eids\\[\\]]').each(function(){ - this.addEventListener('click',configureButton,false); + $j('input[name=eids\\[\\]]').each(function() { + this.addEventListener('click', configureButton, false); + }); + document.getElementById("refreshLink").addEventListener("click", function onRefreshClick(evt) { + evt.preventDefault(); + window.location.reload(true); + }); + document.getElementById("backLink").addEventListener("click", function onBackClick(evt) { + evt.preventDefault(); + window.history.back(); }); } diff --git a/web/skins/classic/views/js/export.js b/web/skins/classic/views/js/export.js index a812e24f4..92b1d9536 100644 --- a/web/skins/classic/views/js/export.js +++ b/web/skins/classic/views/js/export.js @@ -59,6 +59,9 @@ function initPage() { if ( exportReady ) { startDownload.pass( exportFile ).delay( 1500 ); } + document.getElementById('exportButton').addEventListener('click', function onClick() { + exportEvent(this.form); + }); } window.addEventListener( 'DOMContentLoaded', initPage ); diff --git a/web/skins/classic/views/js/frame.js b/web/skins/classic/views/js/frame.js index e0401c7c7..03058ff8a 100644 --- a/web/skins/classic/views/js/frame.js +++ b/web/skins/classic/views/js/frame.js @@ -30,4 +30,10 @@ function changeScale() { }); } -if (scale == 'auto') $j(document).ready(changeScale); +if (scale == 'auto') { + $j(document).ready(changeScale); +} + +document.addEventListener('DOMContentLoaded', function onDCL() { + document.getElementById('scale').addEventListener('change', changeScale); +}); diff --git a/web/skins/classic/views/js/frame.js.php b/web/skins/classic/views/js/frame.js.php index c9b3f2eea..572587f82 100644 --- a/web/skins/classic/views/js/frame.js.php +++ b/web/skins/classic/views/js/frame.js.php @@ -1,3 +1,3 @@ -var scale = ''; +var scale = ''; var SCALE_BASE = ; diff --git a/web/skins/classic/views/js/log.js b/web/skins/classic/views/js/log.js index 49c45c78b..293d425b5 100644 --- a/web/skins/classic/views/js/log.js +++ b/web/skins/classic/views/js/log.js @@ -64,7 +64,16 @@ function logResponse( respObj ) { if ( ( !minLogTime ) || ( log.TimeKey < minLogTime ) ) { minLogTime = log.TimeKey; } - var row = logTable.push( [{content: log.DateTime, properties: {style: 'white-space: nowrap'}}, log.Component, log.Server, log.Pid, log.Code, log.Message, log.File, log.Line] ); + + // Manually create table cells by setting the text since `push` will set HTML which + // can lead to XSS. + let messageCell = new Element('td'); + messageCell.set('text', log.Message); + + let fileCell = new Element('td'); + fileCell.set('text', log.File); + + var row = logTable.push( [{content: log.DateTime, properties: {style: 'white-space: nowrap'}}, log.Component, log.Server, log.Pid, log.Code, messageCell, fileCell, log.Line] ); delete log.Message; row.tr.store( 'log', log ); diff --git a/web/skins/classic/views/js/monitor.js.php b/web/skins/classic/views/js/monitor.js.php index 82127dd8e..6bb6f73ff 100644 --- a/web/skins/classic/views/js/monitor.js.php +++ b/web/skins/classic/views/js/monitor.js.php @@ -133,9 +133,9 @@ function validateForm( form ) { if ( errors.length ) { alert( errors.join( "\n" ) ); - return( false ); + return false; } - return( true ); + return true; } function updateLinkedMonitors( element ) { diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index b50d59996..f21b59baa 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -936,7 +936,7 @@ function initPage() { console.log("No canvas found for monitor " + monitor_id); continue; } - monitor_canvas.addEventListener('click',clickMonitor,false); + monitor_canvas.addEventListener('click', clickMonitor, false); } setSpeed(speedIndex); //setFit(fitMode); // will redraw diff --git a/web/skins/classic/views/log.php b/web/skins/classic/views/log.php index b02ec028e..c2ce0262e 100644 --- a/web/skins/classic/views/log.php +++ b/web/skins/classic/views/log.php @@ -90,7 +90,7 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
- + diff --git a/web/skins/classic/views/login.php b/web/skins/classic/views/login.php index d41634003..c75c9b602 100644 --- a/web/skins/classic/views/login.php +++ b/web/skins/classic/views/login.php @@ -4,7 +4,7 @@ xhtmlHeaders(__FILE__, translate('Login') );
- + @@ -16,7 +16,7 @@ xhtmlHeaders(__FILE__, translate('Login') );
-

account_circle

+

account_circle

diff --git a/web/skins/classic/views/logout.php b/web/skins/classic/views/logout.php index 772bacd80..d68bd2b82 100644 --- a/web/skins/classic/views/logout.php +++ b/web/skins/classic/views/logout.php @@ -25,10 +25,10 @@ xhtmlHeaders(__FILE__, translate('Logout') );
- +

diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index af770eb79..cd082ec1b 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -108,8 +108,8 @@ if ( ! $monitor ) { 'EventPrefix' => 'Event-', 'AnalysisFPSLimit' => '', 'AnalysisUpdateDelay' => 0, - 'MaxFPS' => '30', - 'AlarmMaxFPS' => '30', + 'MaxFPS' => null, + 'AlarmMaxFPS' => null, 'FPSReportInterval' => 100, 'RefBlendPerc' => 6, 'AlarmRefBlendPerc' => 6, @@ -462,7 +462,7 @@ if ( canEdit( 'Monitors' ) ) { if ( isset ($_REQUEST['dupId'])) { ?>
- Configuration cloned from Monitor: + Configuration cloned from Monitor:
$value ) { ?>
- + - - + + @@ -724,7 +724,7 @@ switch ( $tab ) { foreach ( $monitors as $linked_monitor ) { if ( (!$monitor->Id() || ($monitor->Id()!= $linked_monitor['Id'])) && visibleMonitor( $linked_monitor['Id'] ) ) { ?> - + GroupIds() ); V4LMultiBuffer() ? 'checked="checked"' : '' ) ?>/> -
+ Type() == 'NVSocket' ) { @@ -873,7 +873,7 @@ include('_monitor_source_nvsocket.php'); - + Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) { ?> @@ -897,11 +897,11 @@ if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) { } if ( $monitor->Type() == 'Local' ) { ?> - + Type() != 'WebSite' ) { ?> - + @@ -915,7 +915,7 @@ if ( $monitor->Type() == 'Local' ) { } case 'storage' : ?> - + - + Type() == 'Local' ) { @@ -1044,7 +1044,7 @@ if ( $monitor->Type() == 'Local' ) {
()
()
Type() == 'Local' ) {
-      +     
- +
diff --git a/web/skins/classic/views/monitorpreset.php b/web/skins/classic/views/monitorpreset.php index 4a576554e..ef5a6ac01 100644 --- a/web/skins/classic/views/monitorpreset.php +++ b/web/skins/classic/views/monitorpreset.php @@ -41,7 +41,7 @@ xhtmlHeaders(__FILE__, translate('MonitorPreset') );

-
+

diff --git a/web/skins/classic/views/monitorprobe.php b/web/skins/classic/views/monitorprobe.php index ef5fc0b20..ff6bef928 100644 --- a/web/skins/classic/views/monitorprobe.php +++ b/web/skins/classic/views/monitorprobe.php @@ -322,7 +322,7 @@ xhtmlHeaders(__FILE__, translate('MonitorProbe') );

- +

diff --git a/web/skins/classic/views/monitors.php b/web/skins/classic/views/monitors.php index d94e71632..a8d2e9d8d 100644 --- a/web/skins/classic/views/monitors.php +++ b/web/skins/classic/views/monitors.php @@ -48,7 +48,7 @@ xhtmlHeaders(__FILE__, translate('Function'));

The following monitors will have these settings update when you click Save:

', array_map(function($m){return $m->Id().' ' .$m->Name();}, $monitors)); ?> - + diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index cd19a5655..a413441f7 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -144,11 +144,11 @@ if ( $showControl ) { } if ( $showZones ) { ?> - Hide Zones + Hide Zones - Show Zones + Show Zones @@ -176,7 +176,7 @@ if ( $showZones ) { - 'selectLayout(this);', 'id'=>'zmMontageLayout')); ?> + 'selectLayout(this);')); ?> diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index a822febbe..53e8b51cf 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -234,7 +234,7 @@ xhtmlHeaders(__FILE__, translate('MontageReview') );
- +