Merge ../ZoneMinder.master into storageareas

pull/2874/head
Isaac Connor 2018-06-06 13:06:41 -04:00
commit 2b00f1d166
13 changed files with 117 additions and 106 deletions

View File

@ -3,6 +3,11 @@ What's New
1. See the ZoneMinder release notes for a list of new features:
https://github.com/ZoneMinder/zoneminder/releases
2. The contents of the ZoneMinder Apache config file have changed. In
addition, this ZoneMinder package now requires you to manually symlink the
ZoneMinder Apache config file. See new install step 6 and upgrade step 3
below for details.
New installs
============

View File

@ -4,6 +4,11 @@ What's New
1. See the ZoneMinder release notes for a list of new features:
https://github.com/ZoneMinder/zoneminder/releases
2. The contents of the ZoneMinder Apache config file have changed. In
addition, this ZoneMinder package now requires you to manually symlink the
ZoneMinder Apache config file. See new install step 6 and upgrade step 3
below for details.
New installs
============

View File

@ -26,7 +26,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.31.43
Version: 1.31.44
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons

View File

@ -315,7 +315,6 @@ sub run {
$secs_count += 1;
}
my $nfound = select(my $rout = $rin, undef, undef, $timeout);
Debug("Aftere select $nfound");
if ( $nfound > 0 ) {
if ( vec($rout, fileno(SERVER), 1) ) {
my $paddr = accept(CLIENT, SERVER);

View File

@ -22,13 +22,9 @@ if ( sem_acquire($semaphore,1) !== false ) {
if ( file_exists( $localSocketFile ) ) {
Warning("sock file $localSocketFile already exists?! Is someone else talking to zms?");
// They could be. We can maybe have concurrent requests from a browser.
} else {
Logger::Debug("socket file does not exist, we should be good to connect.");
}
if ( ! socket_bind( $socket, $localSocketFile ) ) {
ajaxError( "socket_bind( $localSocketFile ) failed: ".socket_strerror(socket_last_error()) );
} else {
Logger::Debug("Bound to $localSocketFile");
ajaxError("socket_bind( $localSocketFile ) failed: ".socket_strerror(socket_last_error()) );
}
switch ( $_REQUEST['command'] ) {
@ -81,7 +77,6 @@ if ( sem_acquire($semaphore,1) !== false ) {
$eSockets = NULL;
$timeout = MSG_TIMEOUT - ( time() - $start_time );
Logger::Debug("TImeout is: $timeout/1000 seconds. " );
$numSockets = socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 );

View File

@ -332,25 +332,18 @@ class MonitorsController extends AppController {
}
public function daemonControl($id, $command, $monitor=null, $daemon=null) {
$args = '';
$daemons = array();
if (!$monitor) {
if ( !$monitor ) {
// Need to see if it is local or remote
$monitor = $this->Monitor->find('first', array(
'fields' => array('Type', 'Function'),
'fields' => array('Type', 'Function', 'Device'),
'conditions' => array('Id' => $id)
));
$monitor = $monitor['Monitor'];
}
if ($monitor['Type'] == 'Local') {
$args = '-d ' . $monitor['Device'];
} else {
$args = '-m ' . $id;
}
if ($monitor['Function'] == 'Monitor') {
if ( $monitor['Function'] == 'Monitor' ) {
array_push($daemons, 'zmc');
} else {
array_push($daemons, 'zmc', 'zma');
@ -359,6 +352,13 @@ class MonitorsController extends AppController {
$zm_path_bin = Configure::read('ZM_PATH_BIN');
foreach ($daemons as $daemon) {
$args = '';
if ( $daemon == 'zmc' and $monitor['Type'] == 'Local') {
$args = '-d ' . $monitor['Device'];
} else {
$args = '-m ' . $id;
}
$shellcmd = escapeshellcmd("$zm_path_bin/zmdc.pl $command $daemon $args");
$status = exec( $shellcmd );
}

View File

@ -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,
);
public function __construct( $IdOrRow=NULL ) {

View File

@ -476,15 +476,12 @@ if ( canEdit( 'Monitors' ) ) {
);
if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) {
Logger::Debug("Auto selecting server");
$_REQUEST['newMonitor']['ServerId'] = dbFetchOne('SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id');
Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] );
if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) {
$_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID;
Logger::Debug("Auto selecting server to " . ZM_SERVER_ID);
}
} else {
Logger::Debug("NOT Auto selecting server" . $_REQUEST['newMonitor']['ServerId']);
}
$columns = getTableColumns('Monitors');
@ -571,22 +568,23 @@ if ( canEdit( 'Monitors' ) ) {
$restart = true;
} # end if count(changes)
if (
( !isset($_POST['newMonitor']['GroupIds']) )
or
( count($_POST['newMonitor']['GroupIds']) != count($Monitor->GroupIds()) )
or
array_diff($_POST['newMonitor']['GroupIds'], $Monitor->GroupIds())
) {
if ( $Monitor->Id() )
dbQuery('DELETE FROM Groups_Monitors WHERE MonitorId=?', array($mid));
if ( isset($_POST['newMonitor']['GroupIds']) ) {
foreach ( $_POST['newMonitor']['GroupIds'] as $group_id ) {
dbQuery('INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid));
}
if (
( !isset($_POST['newMonitor']['GroupIds']) )
or
( count($_POST['newMonitor']['GroupIds']) != count($Monitor->GroupIds()) )
or
array_diff($_POST['newMonitor']['GroupIds'], $Monitor->GroupIds())
) {
if ( $Monitor->Id() )
dbQuery('DELETE FROM Groups_Monitors WHERE MonitorId=?', array($mid));
if ( isset($_POST['newMonitor']['GroupIds']) ) {
foreach ( $_POST['newMonitor']['GroupIds'] as $group_id ) {
dbQuery('INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid));
}
} // end if there has been a change of groups
}
} // end if there has been a change of groups
if ( ZM_OPT_X10 ) {
$x10Changes = getFormChanges( $x10Monitor, $_REQUEST['newX10Monitor'] );

View File

@ -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' && $view != 'archive' ) {
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != '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();

View File

@ -373,18 +373,13 @@ function xhtmlFooter() {
global $view;
global $skin;
global $running;
if ( canEdit('System') ) {
include("skins/$skin/views/state.php");
if ( canEdit('System') ) {
include("skins/$skin/views/state.php");
}
?>
<?php
}
?>
</body>
<script type="text/javascript">
$j('.chosen').chosen();
</script>
</body>
<script type="text/javascript">$j('.chosen').chosen();</script>
</html>
<?php
} // end xhtmlFooter
?>

View File

@ -279,7 +279,7 @@ foreach( array_map( 'basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
<td class="colScheme"><?php echo makePopupLink( '?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Scheme()), $canEdit ) ?></td>
<td class="colServer"><?php
echo makePopupLink( '?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Name()), $canEdit ) ?></td>
<td class="colDiskSpace"><?php echo human_filesize($Storage->disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?><?td>
<td class="colDiskSpace"><?php echo human_filesize($Storage->disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?></td>
<td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $Storage->Id() ?>" onclick="configureDeleteButton(this);"<?php if ( !$canEdit ) { ?> disabled="disabled"<?php } ?>/></td>
</tr>
<?php } #end foreach Server ?>

View File

@ -18,8 +18,8 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Events' ) ) {
$view = "error";
if ( !canView('Events') ) {
$view = 'error';
return;
}
@ -28,31 +28,31 @@ require_once('includes/Event.php');
$eid = validInt($_REQUEST['eid']);
$sql = 'SELECT E.*,M.Name AS MonitorName,M.DefaultRate,M.DefaultScale FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = ?';
$sql_values = array( $eid );
$sql_values = array($eid);
if ( $user['MonitorIds'] ) {
$monitor_ids = explode( ',', $user['MonitorIds'] );
$sql .= ' AND MonitorId IN (' .implode( ',', array_fill(0,count($monitor_ids),'?') ) . ')';
$sql_values = array_merge( $sql_values, $monitor_ids );
$monitor_ids = explode(',', $user['MonitorIds']);
$sql .= ' AND MonitorId IN ('.implode(',', array_fill(0,count($monitor_ids),'?')).')';
$sql_values = array_merge($sql_values, $monitor_ids);
}
$event = dbFetchOne( $sql, NULL, $sql_values );
$event = dbFetchOne($sql, NULL, $sql_values);
if ( isset( $_REQUEST['rate'] ) )
if ( isset($_REQUEST['rate']) )
$rate = validInt($_REQUEST['rate']);
else
$rate = reScale( RATE_BASE, $event['DefaultRate'], ZM_WEB_DEFAULT_RATE );
if ( isset( $_REQUEST['scale'] ) )
$rate = reScale(RATE_BASE, $event['DefaultRate'], ZM_WEB_DEFAULT_RATE);
if ( isset($_REQUEST['scale']) )
$scale = validInt($_REQUEST['scale']);
else
$scale = reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
$scale = reScale(SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE);
$Event = new Event( $event['Id'] );
$Event = new Event($event['Id']);
$eventPath = $Event->Path();
$videoFormats = array();
$ffmpegFormats = preg_split( '/\s+/', ZM_FFMPEG_FORMATS );
$ffmpegFormats = preg_split('/\s+/', ZM_FFMPEG_FORMATS);
foreach ( $ffmpegFormats as $ffmpegFormat ) {
if ( preg_match( '/^([^*]+)(\*\*?)$/', $ffmpegFormat, $matches ) ) {
if ( preg_match('/^([^*]+)(\*\*?)$/', $ffmpegFormat, $matches) ) {
$videoFormats[$matches[1]] = $matches[1];
if ( !isset($videoFormat) && $matches[2] == '*' ) {
$videoFormat = $matches[1];
@ -63,42 +63,44 @@ foreach ( $ffmpegFormats as $ffmpegFormat ) {
}
$videoFiles = array();
if ( $dir = opendir( $eventPath ) ) {
while ( ($file = readdir( $dir )) !== false ) {
if ( $dir = opendir($eventPath) ) {
while ( ($file = readdir($dir)) !== false ) {
$file = $eventPath.'/'.$file;
if ( is_file( $file ) ) {
if ( preg_match( '/\.(?:'.join( '|', $videoFormats ).')$/', $file ) ) {
if ( is_file($file) ) {
if ( preg_match('/\.(?:'.join('|', $videoFormats).')$/', $file) ) {
$videoFiles[] = $file;
}
}
}
closedir( $dir );
closedir($dir);
}
if ( isset($_REQUEST['deleteIndex']) ) {
$deleteIndex = validInt($_REQUEST['deleteIndex']);
unlink( $videoFiles[$deleteIndex] );
unset( $videoFiles[$deleteIndex] );
unlink($videoFiles[$deleteIndex]);
unset($videoFiles[$deleteIndex]);
}
if ( isset($_REQUEST['downloadIndex']) ) {
// can't be output buffering, as this file might be large
ob_end_clean();
$downloadIndex = validInt($_REQUEST['downloadIndex']);
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="'.basename($videoFiles[$downloadIndex]).'"' ); // basename is required because the video index contains the path and firefox doesn't strip the path but simply replaces the slashes with an underscore.
header( 'Content-Transfer-Encoding: binary' );
header( 'Content-Type: application/force-download' );
header( 'Content-Length: '.filesize($videoFiles[$downloadIndex]) );
readfile( $videoFiles[$downloadIndex] );
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="'.basename($videoFiles[$downloadIndex]).'"'); // basename is required because the video index contains the path and firefox doesn't strip the path but simply replaces the slashes with an underscore.
header('Content-Transfer-Encoding: binary');
header('Content-Type: application/force-download');
header('Content-Length: '.filesize($videoFiles[$downloadIndex]));
readfile($videoFiles[$downloadIndex]);
exit;
}
$focusWindow = true;
xhtmlHeaders(__FILE__, translate('Video') );
xhtmlHeaders(__FILE__, translate('Video'));
?>
<body>
<div id="page">
@ -112,30 +114,30 @@ xhtmlHeaders(__FILE__, translate('Video') );
<?php
if ( isset($_REQUEST['showIndex']) ) {
$showIndex = validInt($_REQUEST['showIndex']);
preg_match( '/([^\/]+)\.([^.]+)$/', $videoFiles[$showIndex], $matches );
preg_match('/([^\/]+)\.([^.]+)$/', $videoFiles[$showIndex], $matches);
$name = $matches[1];
$videoFormat = $matches[2];
?>
<h3 id="videoFile"><?php echo substr( $videoFiles[$showIndex], strlen(ZM_DIR_EVENTS)+1 ) ?></h3>
<div id="imageFeed"><?php outputVideoStream( 'videoStream', $videoFiles[$showIndex], validInt($_REQUEST['width']), validInt($_REQUEST['height']), $videoFormat, $name ) ?></div>
<h3 id="videoFile"><?php echo substr($videoFiles[$showIndex], strlen(ZM_DIR_EVENTS)+1) ?></h3>
<div id="imageFeed"><?php outputVideoStream('videoStream', $videoFiles[$showIndex], validInt($_REQUEST['width']), validInt($_REQUEST['height']), $videoFormat, $name) ?></div>
<?php
} else {
?>
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<input type="hidden" name="id" value="<?php echo $event['Id'] ?>"/>
<table id="contentTable" class="minor" cellspacing="0">
<table id="contentTable" class="minor">
<tbody>
<tr>
<th scope="row"><?php echo translate('VideoFormat') ?></th>
<td><?php echo buildSelect( "videoFormat", $videoFormats ) ?></td>
<td><?php echo buildSelect('videoFormat', $videoFormats) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('FrameRate') ?></th>
<td><?php echo buildSelect( "rate", $rates ) ?></td>
<td><?php echo buildSelect('rate', $rates) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('VideoSize') ?></th>
<td><?php echo buildSelect( "scale", $scales ) ?></td>
<td><?php echo buildSelect('scale', $scales) ?></td>
</tr>
<tr>
<th scope="row"><?php echo translate('OverwriteExisting') ?></th>
@ -143,16 +145,22 @@ if ( isset($_REQUEST['showIndex']) ) {
</tr>
</tbody>
</table>
<input type="button" value="<?php echo translate('GenerateVideo') ?>" onclick="generateVideo( this.form );"<?php if ( !ZM_OPT_FFMPEG ) { ?> disabled="disabled"<?php } ?>/>
<input type="button" value="<?php echo translate('GenerateVideo') ?>" onclick="generateVideo(this.form);"<?php if ( !ZM_OPT_FFMPEG ) { ?> disabled="disabled"<?php } ?>/>
</form>
<?php
if ( isset($_REQUEST['generated']) ) {
?>
<h2 id="videoProgress" class="<?php echo $_REQUEST['generated']?'infoText':'errorText' ?>"><span id="videoProgressText"><?php echo $_REQUEST['generated']?translate('VideoGenSucceeded'):translate('VideoGenFailed') ?></span><span id="videoProgressTicker"></span></h2>
<h2 id="videoProgress" class="<?php echo $_REQUEST['generated']?'infoText':'errorText' ?>">
<span id="videoProgressText"><?php echo $_REQUEST['generated']?translate('VideoGenSucceeded'):translate('VideoGenFailed') ?></span>
<span id="videoProgressTicker"></span>
</h2>
<?php
} else {
?>
<h2 id="videoProgress" class="hidden warnText"><span id="videoProgressText"><?php echo translate('GeneratingVideo') ?></span><span id="videoProgressTicker"></span></h2>
<h2 id="videoProgress" class="hidden warnText">
<span id="videoProgressText"><?php echo translate('GeneratingVideo') ?></span>
<span id="videoProgressTicker"></span>
</h2>
<?php
}
?>
@ -164,7 +172,7 @@ if ( isset($_REQUEST['showIndex']) ) {
<?php
} else {
?>
<table id="videoTable" class="major" cellspacing="0">
<table id="videoTable" class="major">
<thead>
<tr>
<th scope="row"><?php echo translate('Format') ?></th>
@ -178,29 +186,29 @@ if ( isset($_REQUEST['showIndex']) ) {
<?php
$index = 0;
foreach ( $videoFiles as $file ) {
if ( filesize( $file ) > 0 ) {
preg_match( '/^(.+)-((?:r[_\d]+)|(?:F[_\d]+))-((?:s[_\d]+)|(?:S[0-9a-z]+))\.([^.]+)$/', $file, $matches );
if ( preg_match( '/^r(.+)$/', $matches[2], $temp_matches ) ) {
if ( filesize($file) > 0 ) {
preg_match('/^(.+)-((?:r[_\d]+)|(?:F[_\d]+))-((?:s[_\d]+)|(?:S[0-9a-z]+))\.([^.]+)$/', $file, $matches);
if ( preg_match('/^r(.+)$/', $matches[2], $temp_matches) ) {
$rate = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) );
$rateText = isset($rates[$rate])?$rates[$rate]:($rate."x");
} elseif ( preg_match( '/^F(.+)$/', $matches[2], $temp_matches ) ) {
$rateText = $temp_matches[1]."fps";
} elseif ( preg_match('/^F(.+)$/', $matches[2], $temp_matches) ) {
$rateText = $temp_matches[1].'fps';
}
if ( preg_match( '/^s(.+)$/', $matches[3], $temp_matches ) ) {
$scale = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) );
$scaleText = isset($scales[$scale])?$scales[$scale]:($scale."x");
} elseif ( preg_match( '/^S(.+)$/', $matches[3], $temp_matches ) ) {
if ( preg_match('/^s(.+)$/', $matches[3], $temp_matches) ) {
$scale = (int)(100 * preg_replace('/_/', '.', $temp_matches[1]) );
$scaleText = isset($scales[$scale])?$scales[$scale]:($scale.'x');
} elseif ( preg_match('/^S(.+)$/', $matches[3], $temp_matches) ) {
$scaleText = $temp_matches[1];
}
$width = $scale?reScale( $event['Width'], $scale ):$event['Width'];
$height = $scale?reScale( $event['Height'], $scale ):$event['Height'];
$width = $scale?reScale($event['Width'], $scale):$event['Width'];
$height = $scale?reScale($event['Height'], $scale):$event['Height'];
?>
<tr>
<td><?php echo $matches[4] ?></td>
<td><?php echo filesize( $file ) ?></td>
<td><?php echo filesize($file) ?></td>
<td><?php echo $rateText ?></td>
<td><?php echo $scaleText ?></td>
<td><?php echo makePopupLink( '?view='.$view.'&amp;eid='.$event['Id'].'&amp;width='.$width.'&amp;height='.$height.'&amp;showIndex='.$index, 'zmVideo'.$event['Id'].'-'.$scale, array( 'videoview', $width, $height ), translate('View') ); ?>&nbsp;/&nbsp;<a href="<?php echo substr( $file, strlen(ZM_DIR_EVENTS)+1 ) ?>" onclick="downloadVideo( <?php echo $index ?> ); return( false );"><?php echo translate('Download') ?></a>&nbsp;/&nbsp;<a href="#" onclick="deleteVideo( <?php echo $index ?> ); return( false );"><?php echo translate('Delete') ?></a></td>
<td><?php echo makePopupLink('?view='.$view.'&amp;eid='.$event['Id'].'&amp;width='.$width.'&amp;height='.$height.'&amp;showIndex='.$index, 'zmVideo'.$event['Id'].'-'.$scale, array( 'videoview', $width, $height ), translate('View') ); ?>&nbsp;/&nbsp;<a href="<?php echo substr( $file, strlen(ZM_DIR_EVENTS)+1 ) ?>" onclick="downloadVideo( <?php echo $index ?> ); return( false );"><?php echo translate('Download') ?></a>&nbsp;/&nbsp;<a href="#" onclick="deleteVideo( <?php echo $index ?> ); return( false );"><?php echo translate('Delete') ?></a></td>
</tr>
<?php
$index++;

View File

@ -32,7 +32,7 @@
// If both scale and either width or height are specified, scale is ignored
//
if ( !canView( 'Events' ) ) {
if ( !canView('Events') ) {
$view = 'error';
return;
}
@ -85,7 +85,13 @@ if ( empty($_REQUEST['path']) ) {
$Frame->Delta(1);
$Frame->FrameId('snapshot');
}
$path = $Event->Path().'/snapshot.jpg';
$Monitor = $Event->Monitor();
if ( $Monitor->SaveJPEGs() & 1 ) {
# If we store Frames as jpgs, then we don't store a snapshot
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
} else {
$path = $Event->Path().'/snapshot.jpg';
}
} else {
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'FrameId'=>$_REQUEST['fid']));