Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2017-05-05 17:28:47 -04:00
commit 4e7ce479b4
12 changed files with 75 additions and 25 deletions

View File

@ -271,3 +271,8 @@ EXECUTE stmt;
ALTER TABLE Monitors MODIFY EncoderParameters TEXT; ALTER TABLE Monitors MODIFY EncoderParameters TEXT;
ALTER TABLE Monitors MODIFY Path VARCHAR(255); 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;

View File

@ -116,7 +116,7 @@ switch ( $data['type'] )
session_start(); session_start();
$time = time(); $time = time();
// Regenerate auth hash after half the lifetime of the hash // 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 ); $data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
} }
session_write_close(); session_write_close();
@ -134,7 +134,7 @@ switch ( $data['type'] )
session_start(); session_start();
$time = time(); $time = time();
// Regenerate auth hash after half the lifetime of the hash // 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 ); $data['auth'] = generateAuthHash( ZM_AUTH_HASH_IPS );
} }
session_write_close(); session_write_close();

View File

@ -126,7 +126,7 @@ class Event {
} # ! ZM_OPT_FAST_DELETE } # ! ZM_OPT_FAST_DELETE
} # end Event->delete } # end Event->delete
public function getStreamSrc( $args, $querySep='&amp;' ) { public function getStreamSrc( $args=array(), $querySep='&amp;' ) {
if ( $this->{'DefaultVideo'} ) { if ( $this->{'DefaultVideo'} ) {
return ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php?view=view_video&eid='.$this->{'Id'}; return ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php?view=view_video&eid='.$this->{'Id'};
} }

View File

@ -52,7 +52,7 @@ $GLOBALS['csrf']['rewrite-js'] = false;
* place it here. If you change this value, all previously generated tokens * place it here. If you change this value, all previously generated tokens
* will become invalid. * 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 // nota bene: library code should use csrf_get_secret() and not access
// this global directly // this global directly
@ -102,7 +102,7 @@ $GLOBALS['csrf']['user'] = false;
* tokens, and have Squid ignore that cookie for get requests, for anonymous * tokens, and have Squid ignore that cookie for get requests, for anonymous
* users. (If you haven't guessed, this scheme was(?) used for MediaWiki). * 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. * The name of the magic CSRF token that will be placed in all forms, i.e.
@ -188,11 +188,23 @@ function csrf_check($fatal = true) {
$ok = false; $ok = false;
$tokens = ''; $tokens = '';
do { 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 // we don't regenerate a token and check it because some token creation
// schemes are volatile. // schemes are volatile.
$tokens = $_POST[$name]; $tokens = $_POST[$name];
if (!csrf_check_tokens($tokens)) break; if (!csrf_check_tokens($tokens)) {
Debug("Failed checking tokens");
break;
} else {
Debug("Token passed");
}
$ok = true; $ok = true;
} while (false); } while (false);
if ($fatal && !$ok) { if ($fatal && !$ok) {
@ -225,13 +237,13 @@ function csrf_get_tokens() {
csrf_start(); csrf_start();
// These are "strong" algorithms that don't require per se a secret // 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 (session_id()) return 'sid:' . csrf_hash(session_id()) . $ip;
if ($GLOBALS['csrf']['cookie']) { if ($GLOBALS['csrf']['cookie']) {
$val = csrf_generate_secret(); $val = csrf_generate_secret();
setcookie($GLOBALS['csrf']['cookie'], $val); setcookie($GLOBALS['csrf']['cookie'], $val);
return 'cookie:' . csrf_hash($val) . $ip; 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 // These further algorithms require a server-side secret
if (!$secret) return 'invalid'; if (!$secret) return 'invalid';
if ($GLOBALS['csrf']['user'] !== false) { if ($GLOBALS['csrf']['user'] !== false) {
@ -296,23 +308,40 @@ function csrf_check_tokens($tokens) {
* Checks if a token is valid. * Checks if a token is valid.
*/ */
function csrf_check_token($token) { 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); 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); list($x, $time) = explode(',', $token, 2);
if ($GLOBALS['csrf']['expires']) { 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) { switch ($type) {
case 'sid': case 'sid':
{
Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) );
return $value === csrf_hash(session_id(), $time); return $value === csrf_hash(session_id(), $time);
}
case 'cookie': case 'cookie':
$n = $GLOBALS['csrf']['cookie']; $n = $GLOBALS['csrf']['cookie'];
if (!$n) return false; if (!$n) return false;
if (!isset($_COOKIE[$n])) return false; if (!isset($_COOKIE[$n])) return false;
return $value === csrf_hash($_COOKIE[$n], $time); return $value === csrf_hash($_COOKIE[$n], $time);
case 'key': case 'key':
if (!$GLOBALS['csrf']['key']) return false; 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); return $value === csrf_hash($GLOBALS['csrf']['key'], $time);
// We could disable these 'weaker' checks if 'key' was set, but // We could disable these 'weaker' checks if 'key' was set, but
// that doesn't make me feel good then about the cookie-based // that doesn't make me feel good then about the cookie-based

View File

@ -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. # 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. # Only really important if you have a lot of users.
$sql = "SELECT * FROM Users WHERE Enabled = 1 AND Username='".$_SESSION['username']."'"; $sql = "SELECT * FROM Users WHERE Enabled = 1 AND Username='".$_SESSION['username']."'";

View File

@ -175,7 +175,9 @@ foreach ( getSkinIncludes( 'skin.php' ) as $includeFile )
if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) { if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS ) {
if ( empty($user) && ! empty($_REQUEST['auth']) ) { if ( empty($user) && ! empty($_REQUEST['auth']) ) {
Debug("Getting user from auth hash");
if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) { if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) {
Debug("Success Getting user from auth hash");
userLogin( $authUser['Username'], $authUser['Password'], true ); userLogin( $authUser['Username'], $authUser['Password'], true );
} }
} else if ( ! empty($user) ) { } 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 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) ) { if ( ZM_OPT_USE_AUTH && ! isset($user) ) {
Debug("Redirecting to login" );
$view = 'login'; $view = 'login';
} }

View File

@ -80,8 +80,8 @@
border: 1px solid #006699; border: 1px solid #006699;
text-align: center; text-align: center;
padding: 1px; padding: 1px;
width: 100px; width: 102px;
height: 100px; height: 102px;
} }
.ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn { .ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn {

View File

@ -80,8 +80,8 @@
border: 1px solid #006699; border: 1px solid #006699;
text-align: center; text-align: center;
padding: 1px; padding: 1px;
width: 100px; width: 102px;
height: 100px; height: 102px;
} }
.ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn { .ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn {

View File

@ -98,10 +98,10 @@ var $j = jQuery.noConflict();
<script src='https://www.google.com/recaptcha/api.js'></script> <script src='https://www.google.com/recaptcha/api.js'></script>
<?php } else if ( $title == 'Event' ) { <?php } else if ( $title == 'Event' ) {
?> ?>
<link href="skins/<?php echo $skin; ?>/js/video-js.css" rel="stylesheet"> <link href="skins/<?php echo $skin ?>/js/video-js.css" rel="stylesheet">
<script src="skins/<?php echo $skin; ?>/js/video.js"></script> <script src="skins/<?php echo $skin ?>/js/video.js"></script>
<script src="./js/videojs.zoomrotate.js"></script> <script src="./js/videojs.zoomrotate.js"></script>
<script src="skins/<?php echo $skin; ?>/js/moment.min.js"></script> <script src="skins/<?php echo $skin ?>/js/moment.min.js"></script>
<?php <?php
} }
if ( $skinJsPhpFile ) if ( $skinJsPhpFile )

View File

@ -127,7 +127,10 @@ if ( canEdit( 'Events' ) ) {
<div id="editEvent"><a href="#" onclick="editEvent()"><?php echo translate('Edit') ?></a></div> <div id="editEvent"><a href="#" onclick="editEvent()"><?php echo translate('Edit') ?></a></div>
<div id="archiveEvent" class="hidden"><a href="#" onclick="archiveEvent()"><?php echo translate('Archive') ?></a></div> <div id="archiveEvent" class="hidden"><a href="#" onclick="archiveEvent()"><?php echo translate('Archive') ?></a></div>
<div id="unarchiveEvent" class="hidden"><a href="#" onclick="unarchiveEvent()"><?php echo translate('Unarchive') ?></a></div> <div id="unarchiveEvent" class="hidden"><a href="#" onclick="unarchiveEvent()"><?php echo translate('Unarchive') ?></a></div>
<?php if ( $Event->DefaultVideo() ) { ?>
<div id="downloadEventFile"><a href="<?php echo $Event->getStreamSrc()?>">Download MP4</a></div>
<?php <?php
} // end if Event->DefaultVideo
} // end if can edit Events } // end if can edit Events
if ( canView( 'Events' ) ) { if ( canView( 'Events' ) ) {
?> ?>
@ -139,8 +142,8 @@ if ( $Event->SaveJPEGs() & 3 ) { // Analysis or Jpegs
<?php <?php
} // has frames or analysis } // has frames or analysis
?> ?>
<div id="videoEvent"<?php if ( $streamMode == 'video' ) { ?> class="hidden"<?php } ?>><a href="#" onclick="showVideo()"><?php echo translate('Video') ?></a></div> <div id="videoEvent"><a href="#" onclick="videoEvent();"><?php echo translate('Video') ?></a></div>
<div id="exportEvent"><a href="#" onclick="exportEvent()"><?php echo translate('Export') ?></a></div> <div id="exportEvent"><a href="#" onclick="exportEvent();"><?php echo translate('Export') ?></a></div>
</div> </div>
<div id="eventVideo" class=""> <div id="eventVideo" class="">
<?php <?php

View File

@ -701,6 +701,11 @@ function showFrameStats()
createPopup( '?view=stats&eid='+eventData.Id+'&fid='+fid, 'zmStats', 'stats', eventData.Width, eventData.Height ); 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() function drawProgressBar()
{ {

View File

@ -330,19 +330,23 @@ function streamCmdQuery() {
var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate"; var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate";
if ( auth_hash ) if ( auth_hash )
statusCmdParms += '&auth='+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; var statusCmdTimer = null;
function getStatusCmdResponse( respObj, respText ) { function getStatusCmdResponse( respObj, respText ) {
console.log("Got statusCmdQuery");
watchdogOk("status"); watchdogOk("status");
if ( statusCmdTimer ) if ( statusCmdTimer )
statusCmdTimer = clearTimeout( statusCmdTimer ); statusCmdTimer = clearTimeout( statusCmdTimer );
if ( respObj.result == 'Ok' ) { if ( respObj.result == 'Ok' ) {
console.log("Got ok for status");
$('fpsValue').set( 'text', respObj.monitor.FrameRate ); $('fpsValue').set( 'text', respObj.monitor.FrameRate );
setAlarmState( respObj.monitor.Status ); setAlarmState( respObj.monitor.Status );
} else } else {
console.log("Got bad response for status");
checkStreamForErrors("getStatusCmdResponse",respObj); checkStreamForErrors("getStatusCmdResponse",respObj);
}
var statusCmdTimeout = statusRefreshTimeout; var statusCmdTimeout = statusRefreshTimeout;
if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ) if ( alarmState == STATE_ALARM || alarmState == STATE_ALERT )
@ -351,6 +355,7 @@ function getStatusCmdResponse( respObj, respText ) {
} }
function statusCmdQuery() { function statusCmdQuery() {
console.log("Sending statusCmdQuery");
statusCmdReq.send(); statusCmdReq.send();
} }