From 19b2de6d280af70c369261d8bddd247c8e27ce45 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 15:13:25 -0400 Subject: [PATCH 01/17] add a Download MP4 button --- web/skins/classic/views/event.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index 8cde0dd53..e5fe75d14 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -127,7 +127,10 @@ if ( canEdit( 'Events' ) ) {
+DefaultVideo() ) { ?> +
Download MP4
DefaultVideo } // end if can edit Events if ( canView( 'Events' ) ) { ?> From 0982c9fdec8a18c64cc7abd6a4e46f2ce62bd66a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:00:52 -0400 Subject: [PATCH 02/17] add Debug lines --- web/includes/csrf/csrf-magic.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php index 153417f4e..2ed217a58 100644 --- a/web/includes/csrf/csrf-magic.php +++ b/web/includes/csrf/csrf-magic.php @@ -52,7 +52,7 @@ $GLOBALS['csrf']['rewrite-js'] = false; * place it here. If you change this value, all previously generated tokens * will become invalid. */ -$GLOBALS['csrf']['secret'] = ''; +$GLOBALS['csrf']['secret'] = ZM_AUTH_HASH_SECRET; // nota bene: library code should use csrf_get_secret() and not access // this global directly @@ -188,7 +188,13 @@ function csrf_check($fatal = true) { $ok = false; $tokens = ''; do { - if (!isset($_POST[$name])) break; + if (!isset($_POST[$name])) { +Debug("POST[$name] is not set"); +break; +} else { +Debug("POST[$name] is set as " . $_POST[$name] ); + +} // we don't regenerate a token and check it because some token creation // schemes are volatile. $tokens = $_POST[$name]; @@ -296,12 +302,22 @@ function csrf_check_tokens($tokens) { * Checks if a token is valid. */ function csrf_check_token($token) { - if (strpos($token, ':') === false) return false; +Debug("Checking CSRF token $token"); + if (strpos($token, ':') === false) { +Debug("Checking CSRF token $token bad because no :"); + return false; + } list($type, $value) = explode(':', $token, 2); - if (strpos($value, ',') === false) return false; + if (strpos($value, ',') === false) { +Debug("Checking CSRF token $token bad because no ,"); + return false; + } list($x, $time) = explode(',', $token, 2); if ($GLOBALS['csrf']['expires']) { - if (time() > $time + $GLOBALS['csrf']['expires']) return false; + if (time() > $time + $GLOBALS['csrf']['expires']) { +Debug("Checking CSRF token $token bad because expired"); +return false; + } } switch ($type) { case 'sid': From a0e4e6537e10e599926b2c7bebada5168e1fc765 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:11:40 -0400 Subject: [PATCH 03/17] prefer key based tokens over session --- web/includes/csrf/csrf-magic.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php index 2ed217a58..e51d39d15 100644 --- a/web/includes/csrf/csrf-magic.php +++ b/web/includes/csrf/csrf-magic.php @@ -198,7 +198,10 @@ Debug("POST[$name] is set as " . $_POST[$name] ); // we don't regenerate a token and check it because some token creation // schemes are volatile. $tokens = $_POST[$name]; - if (!csrf_check_tokens($tokens)) break; + if (!csrf_check_tokens($tokens)) { +Debug("Failed checking tokens"); +break; +} $ok = true; } while (false); if ($fatal && !$ok) { @@ -231,13 +234,13 @@ function csrf_get_tokens() { csrf_start(); // These are "strong" algorithms that don't require per se a secret + if ($GLOBALS['csrf']['key']) return 'key:' . csrf_hash($GLOBALS['csrf']['key']) . $ip; if (session_id()) return 'sid:' . csrf_hash(session_id()) . $ip; if ($GLOBALS['csrf']['cookie']) { $val = csrf_generate_secret(); setcookie($GLOBALS['csrf']['cookie'], $val); return 'cookie:' . csrf_hash($val) . $ip; } - if ($GLOBALS['csrf']['key']) return 'key:' . csrf_hash($GLOBALS['csrf']['key']) . $ip; // These further algorithms require a server-side secret if (!$secret) return 'invalid'; if ($GLOBALS['csrf']['user'] !== false) { @@ -321,7 +324,10 @@ return false; } switch ($type) { case 'sid': + { + Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) ); return $value === csrf_hash(session_id(), $time); + } case 'cookie': $n = $GLOBALS['csrf']['cookie']; if (!$n) return false; From 1ff367373f18e52c6482c63ad678d6476c9b27e2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:15:34 -0400 Subject: [PATCH 04/17] use ZM_AUTH_HASH_SECRET for the key, not the secret --- web/includes/csrf/csrf-magic.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php index e51d39d15..787349dfb 100644 --- a/web/includes/csrf/csrf-magic.php +++ b/web/includes/csrf/csrf-magic.php @@ -102,7 +102,7 @@ $GLOBALS['csrf']['user'] = false; * tokens, and have Squid ignore that cookie for get requests, for anonymous * users. (If you haven't guessed, this scheme was(?) used for MediaWiki). */ -$GLOBALS['csrf']['key'] = false; +$GLOBALS['csrf']['key'] = ZM_AUTH_HASH_SECRET; /** * The name of the magic CSRF token that will be placed in all forms, i.e. From 64193c336840e4f68990e29b9387300c7afe8517 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:18:12 -0400 Subject: [PATCH 05/17] turn status ajax calls to gets instead of posts --- 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 f11c2aca2..fbb459bde 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -330,7 +330,7 @@ function streamCmdQuery() { var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate"; if ( auth_hash ) statusCmdParms += '&auth='+auth_hash; -var statusCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'post', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } ); +var statusCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'get', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } ); var statusCmdTimer = null; function getStatusCmdResponse( respObj, respText ) { From cb99d709c51559be5df6faef9a86a8da285cd647 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:37:12 -0400 Subject: [PATCH 06/17] add debug --- web/skins/classic/views/js/watch.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index fbb459bde..20a2cafba 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -334,15 +334,19 @@ var statusCmdReq = new Request.JSON( { url: monitorUrl+thisUrl, method: 'get', d var statusCmdTimer = null; function getStatusCmdResponse( respObj, respText ) { +console.log("Got statusCmdQuery"); watchdogOk("status"); if ( statusCmdTimer ) statusCmdTimer = clearTimeout( statusCmdTimer ); if ( respObj.result == 'Ok' ) { +console.log("Got ok for status"); $('fpsValue').set( 'text', respObj.monitor.FrameRate ); setAlarmState( respObj.monitor.Status ); - } else + } else { + console.log("Got bad response for status"); checkStreamForErrors("getStatusCmdResponse",respObj); + } var statusCmdTimeout = statusRefreshTimeout; if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) @@ -351,6 +355,7 @@ function getStatusCmdResponse( respObj, respText ) { } function statusCmdQuery() { +console.log("Sending statusCmdQuery"); statusCmdReq.send(); } From 92854f5cba227eb783f5199e3223d0a8a92d481e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:37:30 -0400 Subject: [PATCH 07/17] more debug --- web/includes/csrf/csrf-magic.php | 11 +++++++++-- web/index.php | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php index 787349dfb..c4d1b7f8e 100644 --- a/web/includes/csrf/csrf-magic.php +++ b/web/includes/csrf/csrf-magic.php @@ -201,6 +201,9 @@ Debug("POST[$name] is set as " . $_POST[$name] ); if (!csrf_check_tokens($tokens)) { Debug("Failed checking tokens"); break; + +} else { +Debug("Token passed"); } $ok = true; } while (false); @@ -334,8 +337,12 @@ return false; if (!isset($_COOKIE[$n])) return false; return $value === csrf_hash($_COOKIE[$n], $time); case 'key': - if (!$GLOBALS['csrf']['key']) return false; - return $value === csrf_hash($GLOBALS['csrf']['key'], $time); + if (!$GLOBALS['csrf']['key']) { + Debug("Checking key: no key set" ); + return false; + } + Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) ); + return $value === csrf_hash($GLOBALS['csrf']['key'], $time); // We could disable these 'weaker' checks if 'key' was set, but // that doesn't make me feel good then about the cookie-based // implementation. diff --git a/web/index.php b/web/index.php index 2e48f852b..282de6cc6 100644 --- a/web/index.php +++ b/web/index.php @@ -175,7 +175,9 @@ foreach ( getSkinIncludes( 'skin.php' ) as $includeFile ) if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) { if ( empty($user) && ! empty($_REQUEST['auth']) ) { +Debug("Getting user from auth hash"); if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) { +Debug("Success Getting user from auth hash"); userLogin( $authUser['Username'], $authUser['Password'], true ); } } else if ( ! empty($user) ) { @@ -206,6 +208,7 @@ require_once( 'includes/actions.php' ); # If I put this here, it protects all views and popups, but it has to go after actions.php because actions.php does the actual logging in. if ( ZM_OPT_USE_AUTH && ! isset($user) ) { + Debug("Redirecting to login" ); $view = 'login'; } From f66b606e348a557b3aa630ed804b32b65cb38442 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:40:05 -0400 Subject: [PATCH 08/17] use isset --- 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 d3d266ce7..0f0441d38 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -118,7 +118,7 @@ function getAuthUser( $auth ) { } } - if ( $_SESSION['username'] ) { + if ( isset( $_SESSION['username'] ) ) { # Most of the time we will be logged in already and the session will have our username, so we can significantly speed up our hash testing by only looking at our user. # Only really important if you have a lot of users. $sql = "SELECT * FROM Users WHERE Enabled = 1 AND Username='".$_SESSION['username']."'"; From deb1cf653a07324d32957ba2de9e196aad4b7db5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:47:21 -0400 Subject: [PATCH 09/17] fix dimensions of ptz box --- web/skins/classic/css/dark/control.css | 4 ++-- web/skins/classic/css/flat/control.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/css/dark/control.css b/web/skins/classic/css/dark/control.css index 737191cd7..cd404583c 100644 --- a/web/skins/classic/css/dark/control.css +++ b/web/skins/classic/css/dark/control.css @@ -80,8 +80,8 @@ border: 1px solid #006699; text-align: center; padding: 1px; - width: 100px; - height: 100px; + width: 102px; + height: 102px; } .ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn { diff --git a/web/skins/classic/css/flat/control.css b/web/skins/classic/css/flat/control.css index 737191cd7..cd404583c 100644 --- a/web/skins/classic/css/flat/control.css +++ b/web/skins/classic/css/flat/control.css @@ -80,8 +80,8 @@ border: 1px solid #006699; text-align: center; padding: 1px; - width: 100px; - height: 100px; + width: 102px; + height: 102px; } .ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn { From fd90de595209fcc63155100e4e7dd594e4b8e14b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:47:50 -0400 Subject: [PATCH 10/17] if no AuthHashGEneratedAt then generate one instead of outputting an error --- web/ajax/stream.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/ajax/stream.php b/web/ajax/stream.php index 463558640..26318dd95 100644 --- a/web/ajax/stream.php +++ b/web/ajax/stream.php @@ -116,7 +116,7 @@ switch ( $data['type'] ) session_start(); $time = time(); // Regenerate auth hash after half the lifetime of the hash - if ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) { + if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) { $data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS ); } session_write_close(); @@ -134,7 +134,7 @@ switch ( $data['type'] ) session_start(); $time = time(); // Regenerate auth hash after half the lifetime of the hash - if ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) { + if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) { $data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS ); } session_write_close(); From 1cd01be0b09721ad901a22f28e77342927c65a82 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:52:30 -0400 Subject: [PATCH 11/17] blah --- db/zm_update-1.30.14.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 db/zm_update-1.30.14.sql diff --git a/db/zm_update-1.30.14.sql b/db/zm_update-1.30.14.sql new file mode 100644 index 000000000..6d9fc3806 --- /dev/null +++ b/db/zm_update-1.30.14.sql @@ -0,0 +1,4 @@ +ALTER TAble Monitors MODIFY V4LMultiBuffer tinyint(1) unsigned; +ALTER TAble Monitors MODIFY ControlId int(10) unsigned; +ALTER TAble Monitors MODIFY TrackDelay smallint(5) unsigned; +ALTER TAble Monitors MODIFY ReturnDelay smallint(5) unsigned; From cb6d7c7c61d26891b7f729889130e8184ae73884 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:53:38 -0400 Subject: [PATCH 12/17] further allow NULL updates --- db/zm_update-1.31.0.sql | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/db/zm_update-1.31.0.sql b/db/zm_update-1.31.0.sql index b3d9c044f..9c4b7f49f 100644 --- a/db/zm_update-1.31.0.sql +++ b/db/zm_update-1.31.0.sql @@ -271,3 +271,8 @@ EXECUTE stmt; ALTER TABLE Monitors MODIFY EncoderParameters TEXT; ALTER TABLE Monitors MODIFY Path VARCHAR(255); + +ALTER TAble Monitors MODIFY V4LMultiBuffer tinyint(1) unsigned; +ALTER TAble Monitors MODIFY ControlId int(10) unsigned; +ALTER TAble Monitors MODIFY TrackDelay smallint(5) unsigned; +ALTER TAble Monitors MODIFY ReturnDelay smallint(5) unsigned; From 6dcad09c6559490edf661887a4914c9e946a89f9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 16:53:49 -0400 Subject: [PATCH 13/17] this was never commited and got lost. Merge it's content into zm_update-1.31.0.sql --- db/zm_update-1.30.14.sql | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 db/zm_update-1.30.14.sql diff --git a/db/zm_update-1.30.14.sql b/db/zm_update-1.30.14.sql deleted file mode 100644 index 6d9fc3806..000000000 --- a/db/zm_update-1.30.14.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TAble Monitors MODIFY V4LMultiBuffer tinyint(1) unsigned; -ALTER TAble Monitors MODIFY ControlId int(10) unsigned; -ALTER TAble Monitors MODIFY TrackDelay smallint(5) unsigned; -ALTER TAble Monitors MODIFY ReturnDelay smallint(5) unsigned; From fe532ac945234f45b8110566b42fc5ef75189871 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 17:17:39 -0400 Subject: [PATCH 14/17] make args not required --- 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 b32a94e94..96d511f81 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -126,7 +126,7 @@ class Event { } # ! ZM_OPT_FAST_DELETE } # end Event->delete - public function getStreamSrc( $args, $querySep='&' ) { + public function getStreamSrc( $args=array(), $querySep='&' ) { if ( $this->{'DefaultVideo'} ) { return ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php?view=view_video&eid='.$this->{'Id'}; } From bde887fc9ca331ac9e1bece0cf2ccf3d3b39b058 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 5 May 2017 17:17:55 -0400 Subject: [PATCH 15/17] remove unneeded ;'s --- web/skins/classic/includes/functions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index ed8c76abd..0a9297a78 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -98,10 +98,10 @@ var $j = jQuery.noConflict(); - - + + - + Date: Fri, 5 May 2017 17:18:48 -0400 Subject: [PATCH 16/17] bring back video popup --- web/skins/classic/views/event.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index e5fe75d14..f443ce0a2 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -142,8 +142,8 @@ if ( $Event->SaveJPEGs() & 3 ) { // Analysis or Jpegs -
class="hidden">
-
+
+
Date: Fri, 5 May 2017 17:19:02 -0400 Subject: [PATCH 17/17] add back videoEvent --- web/skins/classic/views/js/event.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index ebbf6936d..623f778d0 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -701,6 +701,11 @@ function showFrameStats() createPopup( '?view=stats&eid='+eventData.Id+'&fid='+fid, 'zmStats', 'stats', eventData.Width, eventData.Height ); } +function videoEvent() +{ + createPopup( '?view=video&eid='+eventData.Id, 'zmVideo', 'video', eventData.Width, eventData.Height ); +} + function drawProgressBar() {