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

This commit is contained in:
Isaac Connor 2018-06-09 12:19:50 -04:00
commit 09dae432ce
24 changed files with 418 additions and 389 deletions

View File

@ -4,6 +4,11 @@ What's New
1. See the ZoneMinder release notes for a list of new features: 1. See the ZoneMinder release notes for a list of new features:
https://github.com/ZoneMinder/zoneminder/releases 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 New installs
============ ============

View File

@ -4,6 +4,11 @@ What's New
1. See the ZoneMinder release notes for a list of new features: 1. See the ZoneMinder release notes for a list of new features:
https://github.com/ZoneMinder/zoneminder/releases 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 New installs
============ ============

View File

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

View File

@ -245,7 +245,8 @@ sub initialise( @ ) {
$tempSyslogLevel = $level if defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG')); $tempSyslogLevel = $level if defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG'));
if ( $Config{ZM_LOG_DEBUG} ) { if ( $Config{ZM_LOG_DEBUG} ) {
foreach my $target ( split( /\|/, $Config{ZM_LOG_DEBUG_TARGET} ) ) { # Splitting on an empty string doesn't return an empty string, it returns an empty array
foreach my $target ( $Config{ZM_LOG_DEBUG_TARGET} ? split(/\|/, $Config{ZM_LOG_DEBUG_TARGET}) : '' ) {
if ( $target eq $this->{id} if ( $target eq $this->{id}
|| $target eq '_'.$this->{id} || $target eq '_'.$this->{id}
|| $target eq $this->{idRoot} || $target eq $this->{idRoot}
@ -278,6 +279,9 @@ sub initialise( @ ) {
$this->{initialised} = !undef; $this->{initialised} = !undef;
# this function can get called on a previously initialized log Object, so clean any sth's
$this->{sth} = undef;
Debug( 'LogOpts: level='.$codes{$this->{level}} Debug( 'LogOpts: level='.$codes{$this->{level}}
.'/'.$codes{$this->{effectiveLevel}} .'/'.$codes{$this->{effectiveLevel}}
.', screen='.$codes{$this->{termLevel}} .', screen='.$codes{$this->{termLevel}}
@ -319,6 +323,8 @@ sub reinitialise {
my $screenLevel = $this->termLevel(); my $screenLevel = $this->termLevel();
$this->termLevel(NOLOG); $this->termLevel(NOLOG);
$this->termLevel($screenLevel) if $screenLevel > NOLOG; $this->termLevel($screenLevel) if $screenLevel > NOLOG;
$this->{sth} = undef;
} }
# Prevents undefined logging levels # Prevents undefined logging levels
@ -392,6 +398,12 @@ sub level {
# ICON: I am remarking this out because I don't see the point of having an effective level, if we are just going to set it to level. # ICON: I am remarking this out because I don't see the point of having an effective level, if we are just going to set it to level.
#$this->{effectiveLevel} = $this->{level} if ( $this->{level} > $this->{effectiveLevel} ); #$this->{effectiveLevel} = $this->{level} if ( $this->{level} > $this->{effectiveLevel} );
# ICON: The point is that LOG_DEBUG can be set either in db or in env var and will get passed in here.
# So this will turn on debug, even if not output has Debug level turned on. I think it should be the other way around
# ICON: Let's try this line instead. effectiveLevel is 1 DEBUG from above, but LOG_DEBUG is off, then $this->level will be 0, and
# so effectiveLevel will become 0
$this->{effectiveLevel} = $this->{level} if ( $this->{level} < $this->{effectiveLevel} );
} }
return $this->{level}; return $this->{level};
} }
@ -474,7 +486,7 @@ sub openSyslog {
sub closeSyslog { sub closeSyslog {
my $this = shift; my $this = shift;
#closelog(); closelog();
} }
sub logFile { sub logFile {
@ -517,17 +529,19 @@ sub logPrint {
if ( $level <= $this->{effectiveLevel} ) { if ( $level <= $this->{effectiveLevel} ) {
$string =~ s/[\r\n]+$//g; $string =~ s/[\r\n]+$//g;
if ( $level <= $this->{syslogLevel} ) {
my $code = $codes{$level}; syslog($priorities{$level}, $codes{$level}.' [%s]', $string);
}
my ($seconds, $microseconds) = gettimeofday(); my ($seconds, $microseconds) = gettimeofday();
if ( $level <= $this->{fileLevel} or $level <= $this->{termLevel} ) {
my $message = sprintf( my $message = sprintf(
'%s.%06d %s[%d].%s [%s]' '%s.%06d %s[%d].%s [%s]'
, strftime('%x %H:%M:%S', localtime($seconds)) , strftime('%x %H:%M:%S', localtime($seconds))
, $microseconds , $microseconds
, $this->{id} , $this->{id}
, $$ , $$
, $code , $codes{$level}
, $string , $string
); );
if ( $this->{trace} ) { if ( $this->{trace} ) {
@ -535,26 +549,33 @@ sub logPrint {
} else { } else {
$message = $message."\n"; $message = $message."\n";
} }
if ( $level <= $this->{syslogLevel} ) {
syslog($priorities{$level}, $code.' [%s]', $string);
}
print($LOGFILE $message) if $level <= $this->{fileLevel}; print($LOGFILE $message) if $level <= $this->{fileLevel};
print(STDERR $message) if $level <= $this->{termLevel}; print(STDERR $message) if $level <= $this->{termLevel};
}
if ( $level <= $this->{databaseLevel} ) { if ( $level <= $this->{databaseLevel} ) {
if ( ( $this->{dbh} and $this->{dbh}->ping() ) or ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) { if ( ! ( $this->{dbh} and $this->{dbh}->ping() ) ) {
$this->{sth} = undef;
if ( ! ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) {
print(STDERR "Can't log to database: ");
$this->{databaseLevel} = NOLOG;
return;
}
}
my $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NULL )'; my $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NULL )';
$this->{sth} = $this->{dbh}->prepare_cached($sql); $this->{sth} = $this->{dbh}->prepare_cached($sql) if ! $this->{sth};
if ( !$this->{sth} ) { if ( !$this->{sth} ) {
$this->{databaseLevel} = NOLOG; $this->{databaseLevel} = NOLOG;
Error("Can't prepare log entry '$sql': ".$this->{dbh}->errstr()); Error("Can't prepare log entry '$sql': ".$this->{dbh}->errstr());
} else { return;
}
my $res = $this->{sth}->execute($seconds+($microseconds/1000000.0) my $res = $this->{sth}->execute($seconds+($microseconds/1000000.0)
, $this->{id} , $this->{id}
, $$ , $$
, $level , $level
, $code , $codes{$level}
, $string , $string
, $this->{fileName} , $this->{fileName}
); );
@ -562,10 +583,6 @@ sub logPrint {
$this->{databaseLevel} = NOLOG; $this->{databaseLevel} = NOLOG;
Error("Can't execute log entry '$sql': ".$this->{dbh}->errstr()); Error("Can't execute log entry '$sql': ".$this->{dbh}->errstr());
} }
}
} else {
print(STDERR "Can't log to database: ");
}
} # end if doing db logging } # end if doing db logging
} # end if level < effectivelevel } # end if level < effectivelevel
} }

View File

@ -139,7 +139,7 @@ foreach my $arg ( @ARGV ) {
# Detaint arguments, if they look ok # Detaint arguments, if they look ok
#if ( $arg =~ /^(-{0,2}[\w]+)/ ) #if ( $arg =~ /^(-{0,2}[\w]+)/ )
if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) { if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) {
push( @args, $1 ); push @args, $1;
} else { } else {
print(STDERR "Bogus argument '$arg' found"); print(STDERR "Bogus argument '$arg' found");
exit(-1); exit(-1);
@ -245,6 +245,16 @@ our %terminating_processes;
our $zm_terminate = 0; our $zm_terminate = 0;
sub run { sub run {
# Call this first otherwise stdout/stderror redirects to the pidfile = bad
if ( open(my $PID, '>', ZM_PID) ) {
print($PID $$);
close($PID);
} else {
# Log not initialized at this point so use die instead
die "Can't open pid file at ".ZM_PID."\n";
}
my $fd = 0; my $fd = 0;
while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) { while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
POSIX::close($fd++); POSIX::close($fd++);
@ -252,6 +262,8 @@ sub run {
setpgrp(); setpgrp();
# dbh got closed with the rest of the fd's above, so need to reconnect.
my $dbh = zmDbConnect(1);
logInit(); logInit();
dPrint(ZoneMinder::Logger::INFO, 'Server starting at ' dPrint(ZoneMinder::Logger::INFO, 'Server starting at '
@ -259,18 +271,10 @@ sub run {
."\n" ."\n"
); );
if ( open(my $PID, '>', ZM_PID) ) {
print($PID $$);
close($PID);
} else {
Error("Can't open pid file at " . ZM_PID);
}
# Tell any existing processes to die, wait 1 second between TERM and KILL # Tell any existing processes to die, wait 1 second between TERM and KILL
killAll(1); killAll(1);
dPrint(ZoneMinder::Logger::INFO, 'Socket should be open at ' .main::SOCK_FILE); dPrint(ZoneMinder::Logger::INFO, 'Socket should be open at ' .main::SOCK_FILE);
my $dbh = zmDbConnect(1);
socket(SERVER, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!"); socket(SERVER, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
unlink(main::SOCK_FILE) or Error('Unable to unlink ' . main::SOCK_FILE .". Error message was: $!") if -e main::SOCK_FILE; unlink(main::SOCK_FILE) or Error('Unable to unlink ' . main::SOCK_FILE .". Error message was: $!") if -e main::SOCK_FILE;
bind(SERVER, $saddr) or Fatal("Can't bind to " . main::SOCK_FILE . ": $!"); bind(SERVER, $saddr) or Fatal("Can't bind to " . main::SOCK_FILE . ": $!");
@ -306,7 +310,7 @@ sub run {
$dbh = zmDbConnect(); $dbh = zmDbConnect();
} }
my @cpuload = CpuLoad(); my @cpuload = CpuLoad();
Debug("UPdating Server record @cpuload"); Debug("Updating Server record @cpuload");
if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,CpuLoad=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef, if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,CpuLoad=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef,
'Running', $cpuload[0], &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) { 'Running', $cpuload[0], &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr()); Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr());
@ -315,7 +319,6 @@ sub run {
$secs_count += 1; $secs_count += 1;
} }
my $nfound = select(my $rout = $rin, undef, undef, $timeout); my $nfound = select(my $rout = $rin, undef, undef, $timeout);
Debug("Aftere select $nfound");
if ( $nfound > 0 ) { if ( $nfound > 0 ) {
if ( vec($rout, fileno(SERVER), 1) ) { if ( vec($rout, fileno(SERVER), 1) ) {
my $paddr = accept(CLIENT, SERVER); my $paddr = accept(CLIENT, SERVER);
@ -370,9 +373,7 @@ Debug("Aftere select $nfound");
#print( "Select timed out\n" ); #print( "Select timed out\n" );
} }
Debug("restartPending");
restartPending(); restartPending();
Debug("check_for_processes_to_kill");
check_for_processes_to_kill(); check_for_processes_to_kill();
} # end while } # end while
@ -382,7 +383,7 @@ Debug("check_for_processes_to_kill");
."\n" ."\n"
); );
if ( $Config{ZM_SERVER_ID} ) { if ( $Config{ZM_SERVER_ID} ) {
$dbh = zmDbConnect() if ! $dbh->ping(); $dbh = zmDbConnect() if ! ($dbh and $dbh->ping());
if ( ! defined $dbh->do(q{UPDATE Servers SET Status='NotRunning' WHERE Id=?}, undef, $Config{ZM_SERVER_ID}) ) { if ( ! defined $dbh->do(q{UPDATE Servers SET Status='NotRunning' WHERE Id=?}, undef, $Config{ZM_SERVER_ID}) ) {
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr()); Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr());
} }
@ -399,6 +400,7 @@ sub cPrint {
# I think the purpose of this is to echo the logs to the client process so it can then display them. # I think the purpose of this is to echo the logs to the client process so it can then display them.
sub dPrint { sub dPrint {
my $logLevel = shift; my $logLevel = shift;
# One thought here, if no client exists to read these... does it block?
if ( fileno(CLIENT) ) { if ( fileno(CLIENT) ) {
print CLIENT @_ print CLIENT @_
} }
@ -435,12 +437,10 @@ sub start {
my $sigset = POSIX::SigSet->new; my $sigset = POSIX::SigSet->new;
my $blockset = POSIX::SigSet->new(SIGCHLD); my $blockset = POSIX::SigSet->new(SIGCHLD);
Debug("Blocking SIGCHLD");
sigprocmask(SIG_BLOCK, $blockset, $sigset) or Fatal("Can't block SIGCHLD: $!"); sigprocmask(SIG_BLOCK, $blockset, $sigset) or Fatal("Can't block SIGCHLD: $!");
Debug("forking");
if ( my $cpid = fork() ) { if ( my $cpid = fork() ) {
# This logReinit is required. Not sure why. # This logReinit is required. Not sure why.
logReinit(); #logReinit();
$process->{pid} = $cpid; $process->{pid} = $cpid;
$process->{started} = time(); $process->{started} = time();
@ -453,7 +453,6 @@ sub start {
$cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process; $cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process;
sigprocmask(SIG_SETMASK, $sigset) or Fatal("Can't restore SIGCHLD: $!"); sigprocmask(SIG_SETMASK, $sigset) or Fatal("Can't restore SIGCHLD: $!");
Debug("unblocking child");
} elsif ( defined($cpid) ) { } elsif ( defined($cpid) ) {
# Force reconnection to the db. # Force reconnection to the db.
$dbh = zmDbConnect(1); $dbh = zmDbConnect(1);
@ -708,7 +707,6 @@ sub reaper {
} # end while waitpid } # end while waitpid
$SIG{CHLD} = \&reaper; $SIG{CHLD} = \&reaper;
$! = $saved_status; $! = $saved_status;
Debug("Leaving reaper");
} }
sub restartPending { sub restartPending {
@ -720,7 +718,6 @@ sub restartPending {
start($process->{daemon}, @{$process->{args}}); start($process->{daemon}, @{$process->{args}});
} }
} }
Debug("done restartPending");
} }
sub shutdownAll { sub shutdownAll {

View File

@ -70,12 +70,14 @@ use Getopt::Long;
use autouse 'Pod::Usage'=>qw(pod2usage); use autouse 'Pod::Usage'=>qw(pod2usage);
use autouse 'Data::Dumper'=>qw(Dumper); use autouse 'Data::Dumper'=>qw(Dumper);
my $daemon = 0;
my $filter_name = ''; my $filter_name = '';
my $filter_id; my $filter_id;
my $version = 0; my $version = 0;
my $zm_terminate = 0; my $zm_terminate = 0;
GetOptions( GetOptions(
'daemon' =>\$daemon,
'filter=s' =>\$filter_name, 'filter=s' =>\$filter_name,
'filter_id=s' =>\$filter_id, 'filter_id=s' =>\$filter_id,
'version' =>\$version 'version' =>\$version
@ -201,7 +203,7 @@ while( !$zm_terminate ) {
} }
} }
last if $filter_name or $filter_id or $zm_terminate; last if (!$daemon and ($filter_name or $filter_id)) or $zm_terminate;
Debug("Sleeping for $delay seconds\n"); Debug("Sleeping for $delay seconds\n");
sleep($delay); sleep($delay);

View File

@ -41,9 +41,10 @@ use autouse 'Pod::Usage'=>qw(pod2usage);
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
my $store_state=""; # PP - will remember state name passed my $store_state=''; # PP - will remember state name passed
logInit(); logInit();
Info("Aftere LogInit");
my $command = $ARGV[0]||''; my $command = $ARGV[0]||'';
if ( $command eq 'version' ) { if ( $command eq 'version' ) {
@ -53,11 +54,10 @@ if ( $command eq 'version' ) {
my $state; my $state;
my $dbh; my $dbh = zmDbConnect();
Info("Command: $command");
if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) { if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) {
if ( $command ) { if ( $command ) {
$dbh = zmDbConnect();
# Check to see if it's a valid run state # Check to see if it's a valid run state
my $sql = 'SELECT * FROM States WHERE Name=?'; my $sql = 'SELECT * FROM States WHERE Name=?';
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
@ -65,10 +65,10 @@ if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ )
my $res = $sth->execute($command) my $res = $sth->execute($command)
or Fatal("Can't execute: ".$sth->errstr()); or Fatal("Can't execute: ".$sth->errstr());
if ( $state = $sth->fetchrow_hashref() ) { if ( $state = $sth->fetchrow_hashref() ) {
$state->{Name} = $command; #$state->{Name} = $command;
$state->{Definitions} = []; $state->{Definitions} = [];
foreach( split( /,/, $state->{Definition} ) ) { foreach( split(',', $state->{Definition}) ) {
my ( $id, $function, $enabled ) = split( /:/, $_ ); my ( $id, $function, $enabled ) = split(':', $_);
push( @{$state->{Definitions}}, push( @{$state->{Definitions}},
{ Id=>$id, Function=>$function, Enabled=>$enabled } { Id=>$id, Function=>$function, Enabled=>$enabled }
); );
@ -82,24 +82,26 @@ if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ )
if ( !$command ) { if ( !$command ) {
pod2usage(-exitstatus => -1); pod2usage(-exitstatus => -1);
} }
} } # end if not one of the usual commands
$dbh = zmDbConnect() if ! $dbh;
# PP - Sane state check # PP - Sane state check
Debug("StartisActiveSSantiyCheck");
isActiveSanityCheck(); isActiveSanityCheck();
Debug("Done isActiveSSantiyCheck");
# Move to the right place # Move to the right place
chdir($Config{ZM_PATH_WEB}) chdir($Config{ZM_PATH_WEB})
or Fatal( "Can't chdir to '".$Config{ZM_PATH_WEB}."': $!" ); or Fatal("Can't chdir to '$Config{ZM_PATH_WEB}': $!");
my $dbg_id = ''; my $dbg_id = '';
Info( "Command: $command\n" ); Info("Command: $command");
my $retval = 0; my $retval = 0;
if ( $command eq 'state' ) { if ( $command eq 'state' ) {
Info( "Updating DB: $state->{Name}\n" ); Info("Updating DB: $state->{Name}");
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=? ORDER BY Id ASC' : 'SELECT * FROM Monitors ORDER BY Id ASC'; my $sql = 'SELECT * FROM Monitors' . ($Config{ZM_SERVER_ID} ? ' WHERE ServerId=?' : '' ) .' ORDER BY Id ASC';
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute($Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: ()) my $res = $sth->execute($Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID}: ())
@ -124,14 +126,14 @@ chdir( $Config{ZM_PATH_WEB} )
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute($monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id}) my $res = $sth->execute($monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id})
or Fatal("Can't execute: ".$sth->errstr()); or Fatal("Can't execute: ".$sth->errstr());
} } # end if change of function or enablement
} } # end foreach monitor
$sth->finish(); $sth->finish();
# PP - Now mark a specific state as active # PP - Now mark a specific state as active
resetStates(); resetStates();
Info("Marking $store_state as Enabled"); Info("Marking $store_state as Enabled");
$sql = "UPDATE States SET IsActive = '1' WHERE Name = ?"; $sql = 'UPDATE States SET IsActive = 1 WHERE Name = ?';
$sth = $dbh->prepare_cached($sql) $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute($store_state) $res = $sth->execute($store_state)
@ -139,7 +141,7 @@ chdir( $Config{ZM_PATH_WEB} )
# PP - zero out other states isActive # PP - zero out other states isActive
$command = 'restart'; $command = 'restart';
} } # end if command = state
# Check if we are running systemd and if we have been called by the system # Check if we are running systemd and if we have been called by the system
if ( $command =~ /^(start|stop|restart)$/ ) { if ( $command =~ /^(start|stop|restart)$/ ) {
@ -154,6 +156,7 @@ if ( $command =~ /^(start|stop|restart)$/ ) {
if ( $command =~ /^(?:stop|restart)$/ ) { if ( $command =~ /^(?:stop|restart)$/ ) {
my $status = runCommand('zmdc.pl check'); my $status = runCommand('zmdc.pl check');
Debug("zmdc.pl check = $status");
if ( $status eq 'running' ) { if ( $status eq 'running' ) {
runCommand('zmdc.pl shutdown'); runCommand('zmdc.pl shutdown');
@ -163,10 +166,9 @@ if ( $command =~ /^(?:stop|restart)$/ ) {
} }
} }
#runCommand( "zmupdate.pl -f" );
if ( $command =~ /^(?:start|restart)$/ ) { if ( $command =~ /^(?:start|restart)$/ ) {
my $status = runCommand('zmdc.pl check'); my $status = runCommand('zmdc.pl check');
Debug("zmdc.pl check = $status");
if ( $status eq 'stopped' ) { if ( $status eq 'stopped' ) {
if ( $Config{ZM_DYN_DB_VERSION} if ( $Config{ZM_DYN_DB_VERSION}
@ -196,7 +198,7 @@ if ( $command =~ /^(?:start|restart)$/ ) {
my @values; my @values;
if ( $Config{ZM_SERVER_ID} ) { if ( $Config{ZM_SERVER_ID} ) {
require ZoneMinder::Server; require ZoneMinder::Server;
Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n"); Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}");
$Server = new ZoneMinder::Server($Config{ZM_SERVER_ID}); $Server = new ZoneMinder::Server($Config{ZM_SERVER_ID});
$sql = 'SELECT * FROM Monitors WHERE ServerId=?'; $sql = 'SELECT * FROM Monitors WHERE ServerId=?';
@values = ( $Config{ZM_SERVER_ID} ); @values = ( $Config{ZM_SERVER_ID} );
@ -221,16 +223,19 @@ if ( $command =~ /^(?:start|restart)$/ ) {
runCommand("zmdc.pl start zma -m $monitor->{Id}"); runCommand("zmdc.pl start zma -m $monitor->{Id}");
} }
if ( $Config{ZM_OPT_CONTROL} ) { if ( $Config{ZM_OPT_CONTROL} ) {
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) { if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) {
if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) {
runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" ); runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" );
} } else {
} Warning(' Monitor is set to track motion, but does not have motion detection enabled.');
} } # end if Has motion enabled
} } # end if track motion
} } # end if ZM_OPT_CONTROL
} # end if function is not none or Website
} # end foreach monitor
$sth->finish(); $sth->finish();
} }
{ {
my $sql = 'SELECT Id FROM Filters WHERE Background=1'; my $sql = 'SELECT Id FROM Filters WHERE Background=1';
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
@ -240,7 +245,7 @@ if ( $command =~ /^(?:start|restart)$/ ) {
if ( $sth->rows ) { if ( $sth->rows ) {
while( my $filter = $sth->fetchrow_hashref() ) { while( my $filter = $sth->fetchrow_hashref() ) {
# This is now started unconditionally # This is now started unconditionally
runCommand("zmdc.pl start zmfilter.pl --filter_id=$$filter{Id}"); runCommand("zmdc.pl start zmfilter.pl --filter_id=$$filter{Id} --daemon");
} }
} else { } else {
runCommand('zmdc.pl start zmfilter.pl'); runCommand('zmdc.pl start zmfilter.pl');
@ -283,7 +288,7 @@ if ( $command =~ /^(?:start|restart)$/ ) {
} else { } else {
$retval = 1; $retval = 1;
} }
} } # end if command is start or restart
if ( $command eq 'status' ) { if ( $command eq 'status' ) {
my $status = runCommand('zmdc.pl check'); my $status = runCommand('zmdc.pl check');
@ -302,7 +307,7 @@ sub isActiveSanityCheck {
$dbh = zmDbConnect() if ! $dbh; $dbh = zmDbConnect() if ! $dbh;
# PP - First, make sure default exists and there is only one # PP - First, make sure default exists and there is only one
my $sql = "SELECT Name FROM States WHERE Name='default'"; my $sql = q`SELECT Name FROM States WHERE Name='default'`;
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute() my $res = $sth->execute()
@ -316,16 +321,15 @@ sub isActiveSanityCheck {
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
$res = $sth->execute() $res = $sth->execute()
or Fatal( "Can't execute: ".$sth->errstr() ); or Fatal( "Can't execute: ".$sth->errstr() );
$sql = "INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');"; $sql = q`"INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');`;
$sth = $dbh->prepare_cached($sql) $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute() $res = $sth->execute()
or Fatal("Can't execute: ".$sth->errstr()); or Fatal("Can't execute: ".$sth->errstr());
} }
# PP - Now make sure no two states have IsActive=1 # PP - Now make sure no two states have IsActive=1
$sql = "SELECT Name FROM States WHERE IsActive = '1'"; $sql = 'SELECT Name FROM States WHERE IsActive = 1';
$sth = $dbh->prepare_cached($sql) $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute() $res = $sth->execute()
@ -334,51 +338,36 @@ sub isActiveSanityCheck {
if ( $sth->rows != 1 ) { if ( $sth->rows != 1 ) {
Info('Fixing States table so only one run state is active'); Info('Fixing States table so only one run state is active');
resetStates(); resetStates();
$sql = "UPDATE States SET IsActive='1' WHERE Name='default'"; $sql = q`UPDATE States SET IsActive=1 WHERE Name='default'`;
$sth = $dbh->prepare_cached($sql) $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
$res = $sth->execute() $res = $sth->execute()
or Fatal("Can't execute: ".$sth->errstr()); or Fatal("Can't execute: ".$sth->errstr());
} }
} } # end sub isActiveSanityCheck
# PP - zeroes out isActive for all states # PP - zeroes out isActive for all states
sub resetStates { sub resetStates {
$dbh = zmDbConnect() if ! $dbh; $dbh = zmDbConnect() if ! $dbh;
my $sql = "UPDATE States SET IsActive='0'"; my $sql = 'UPDATE States SET IsActive=0';
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
or Fatal("Can't prepare '$sql': ".$dbh->errstr()); or Fatal("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute() my $res = $sth->execute()
or Fatal("Can't execute: ".$sth->errstr()); or Fatal("Can't execute: ".$sth->errstr());
} }
sub systemdRunning { sub systemdRunning {
my $result = 0;
my $output = qx(ps -o comm="" -p 1); my $output = qx(ps -o comm="" -p 1);
chomp( $output ); return scalar ( $output =~ /systemd/ );
if ( $output =~ /systemd/ ) {
$result = 1;
}
return $result;
} }
sub calledBysystem { sub calledBysystem {
my $result = 0;
my $ppid = getppid(); my $ppid = getppid();
my $output = qx(ps -o comm="" -p $ppid); my $output = qx(ps -o comm="" -p $ppid);
chomp( $output ); #chomp( $output );
if ($output =~ /^(?:systemd|init)$/) { return ($output =~ /^(?:systemd|init)$/);
$result = 1;
}
return $result;
} }
sub verifyFolder { sub verifyFolder {
@ -394,16 +383,14 @@ sub verifyFolder {
# Not running as web user, so should be root in which case # Not running as web user, so should be root in which case
# chown the directory # chown the directory
my ( $webName, $webPass, $webUid, $webGid ) = getpwnam($Config{ZM_WEB_USER}) my ( $webName, $webPass, $webUid, $webGid ) = getpwnam($Config{ZM_WEB_USER})
or Fatal( "Can't get user details for web user '" or Fatal("Can't get details for web user '$Config{ZM_WEB_USER}': $!");
.$Config{ZM_WEB_USER}."': $!" chown($webUid, $webGid, $folder)
or Fatal("Can't change ownership of '$folder' to '"
.$Config{ZM_WEB_USER}.':'.$Config{ZM_WEB_GROUP}."': $!"
); );
chown( $webUid, $webGid, "$folder" ) } # end if runName ne ZM_WEB_USER
or Fatal( "Can't change ownership of directory '$folder' to '" } # end if folder doesn't exist
.$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!" } # end sub verifyFolder
);
}
}
}
1; 1;
__END__ __END__

View File

@ -24,7 +24,7 @@
#include "zm_db.h" #include "zm_db.h"
MYSQL dbconn; MYSQL dbconn;
Mutex db_mutex; RecursiveMutex db_mutex;
bool zmDbConnected = false; bool zmDbConnected = false;
@ -98,8 +98,8 @@ MYSQL_RES * zmDbFetch(const char * query) {
db_mutex.lock(); db_mutex.lock();
if ( mysql_query(&dbconn, query) ) { if ( mysql_query(&dbconn, query) ) {
Error("Can't run query: %s", mysql_error(&dbconn));
db_mutex.unlock(); db_mutex.unlock();
Error("Can't run query: %s", mysql_error(&dbconn));
return NULL; return NULL;
} }
Debug(4, "Success running query: %s", query); Debug(4, "Success running query: %s", query);

View File

@ -41,7 +41,7 @@ class zmDbRow {
}; };
extern MYSQL dbconn; extern MYSQL dbconn;
extern Mutex db_mutex; extern RecursiveMutex db_mutex;
bool zmDbConnect(); bool zmDbConnect();
void zmDbClose(); void zmDbClose();

View File

@ -95,6 +95,15 @@ bool Mutex::locked() {
return( state == EBUSY ); return( state == EBUSY );
} }
RecursiveMutex::RecursiveMutex() {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
if ( pthread_mutex_init(&mMutex, &attr) < 0 )
Error("Unable to create pthread mutex: %s", strerror(errno));
}
Condition::Condition( Mutex &mutex ) : mMutex( mutex ) { Condition::Condition( Mutex &mutex ) : mMutex( mutex ) {
if ( pthread_cond_init( &mCondition, NULL ) < 0 ) if ( pthread_cond_init( &mCondition, NULL ) < 0 )
throw ThreadException( stringtf( "Unable to create pthread condition: %s", strerror(errno) ) ); throw ThreadException( stringtf( "Unable to create pthread condition: %s", strerror(errno) ) );

View File

@ -70,7 +70,7 @@ public:
private: private:
pthread_mutex_t *getMutex() { pthread_mutex_t *getMutex() {
return( &mMutex ); return &mMutex;
} }
public: public:
@ -82,6 +82,13 @@ public:
bool locked(); bool locked();
}; };
class RecursiveMutex : public Mutex {
private:
pthread_mutex_t mMutex;
public:
RecursiveMutex();
};
class ScopedMutex { class ScopedMutex {
private: private:
Mutex &mMutex; Mutex &mMutex;

View File

@ -86,7 +86,6 @@ int main( int argc, const char *argv[] ) {
zmLoadConfig(); zmLoadConfig();
const char *query = getenv("QUERY_STRING"); const char *query = getenv("QUERY_STRING");
if ( query ) { if ( query ) {
Debug(1, "Query: %s", query); Debug(1, "Query: %s", query);
@ -204,10 +203,10 @@ int main( int argc, const char *argv[] ) {
Error("Unable to authenticate user"); Error("Unable to authenticate user");
logTerm(); logTerm();
zmDbClose(); zmDbClose();
return( -1 ); return -1;
} }
ValidateAccess(user, monitor_id); ValidateAccess(user, monitor_id);
} } // end if config.opt_use_auth
hwcaps_detect(); hwcaps_detect();
zmSetDefaultTermHandler(); zmSetDefaultTermHandler();

View File

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

View File

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

View File

@ -20,7 +20,7 @@ public $defaults = array(
'limit' => 100, 'limit' => 100,
'Query' => array(), 'Query' => array(),
'sort_field' => ZM_WEB_EVENT_SORT_FIELD, '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 ) { public function __construct( $IdOrRow=NULL ) {

View File

@ -476,15 +476,12 @@ if ( canEdit( 'Monitors' ) ) {
); );
if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) { 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'); $_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'] ); Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] );
if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) { if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) {
$_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID; $_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID;
Logger::Debug("Auto selecting server to " . 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'); $columns = getTableColumns('Monitors');
@ -571,6 +568,7 @@ if ( canEdit( 'Monitors' ) ) {
$restart = true; $restart = true;
} # end if count(changes) } # end if count(changes)
if ( if (
( !isset($_POST['newMonitor']['GroupIds']) ) ( !isset($_POST['newMonitor']['GroupIds']) )
or or

View File

@ -200,7 +200,7 @@ isset($view) || $view = NULL;
isset($request) || $request = NULL; isset($request) || $request = NULL;
isset($action) || $action = 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' ); require_once( 'includes/csrf/csrf-magic.php' );
#Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); #Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
csrf_check(); csrf_check();

View File

@ -38,13 +38,6 @@
text-align: center; text-align: center;
} }
#dvrControls input {
height: 20px;
width: 28px;
padding-bottom: 3px;
margin: 0 3px;
}
#dvrControls input[disabled] { #dvrControls input[disabled] {
color: #aaaaaa; color: #aaaaaa;
} }

View File

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

View File

@ -192,7 +192,13 @@ if ( currentView != 'none' ) {
}); });
function getNavBar() { function getNavBar() {
$j.getJSON(thisUrl + '?view=request&request=status&entity=navBar', setNavBar); $j.getJSON(thisUrl + '?view=request&request=status&entity=navBar')
.done(setNavBar)
.fail(function( jqxhr, textStatus, error ) {
var err = textStatus + ", " + error;
console.log( "Request Failed: " + err );
window.location.href = thisUrl;
});
} }
function setNavBar(data) { function setNavBar(data) {

View File

@ -223,7 +223,7 @@ ob_start();
<?php } ?> <?php } ?>
</tr> </tr>
</thead> </thead>
<tbody class="consoleTableBody"> <tbody id="consoleTableBody">
<?php <?php
$table_head = ob_get_contents(); $table_head = ob_get_contents();
ob_end_clean(); ob_end_clean();
@ -318,7 +318,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
<?php <?php
} }
?> ?>
<td class="colZones"><?php echo makePopupLink( '?view=zones&amp;mid='.$monitor['Id'], 'zmZones', array( 'zones', $monitor['Width'], $monitor['Height'] ), $monitor['ZoneCount'], $running && canView('Monitors') ) ?></td> <td class="colZones"><?php echo makePopupLink('?view=zones&amp;mid='.$monitor['Id'], 'zmZones', array('zones', $monitor['Width'], $monitor['Height']), $monitor['ZoneCount'], canView('Monitors')) ?></td>
<?php <?php
if ( canEdit('Monitors') ) { if ( canEdit('Monitors') ) {
?> ?>

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="colScheme"><?php echo makePopupLink( '?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Scheme()), $canEdit ) ?></td>
<td class="colServer"><?php <td class="colServer"><?php
echo makePopupLink( '?view=storage&amp;id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Name()), $canEdit ) ?></td> 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> <td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $Storage->Id() ?>" onclick="configureDeleteButton(this);"<?php if ( !$canEdit ) { ?> disabled="disabled"<?php } ?>/></td>
</tr> </tr>
<?php } #end foreach Server ?> <?php } #end foreach Server ?>

View File

@ -19,7 +19,7 @@
// //
if ( !canView('Events') ) { if ( !canView('Events') ) {
$view = "error"; $view = 'error';
return; return;
} }
@ -82,6 +82,8 @@ if ( isset($_REQUEST['deleteIndex']) ) {
} }
if ( isset($_REQUEST['downloadIndex']) ) { if ( isset($_REQUEST['downloadIndex']) ) {
// can't be output buffering, as this file might be large
ob_end_clean();
$downloadIndex = validInt($_REQUEST['downloadIndex']); $downloadIndex = validInt($_REQUEST['downloadIndex']);
header('Pragma: public'); header('Pragma: public');
header('Expires: 0'); header('Expires: 0');
@ -123,19 +125,19 @@ if ( isset($_REQUEST['showIndex']) ) {
?> ?>
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>"> <form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<input type="hidden" name="id" value="<?php echo $event['Id'] ?>"/> <input type="hidden" name="id" value="<?php echo $event['Id'] ?>"/>
<table id="contentTable" class="minor" cellspacing="0"> <table id="contentTable" class="minor">
<tbody> <tbody>
<tr> <tr>
<th scope="row"><?php echo translate('VideoFormat') ?></th> <th scope="row"><?php echo translate('VideoFormat') ?></th>
<td><?php echo buildSelect( "videoFormat", $videoFormats ) ?></td> <td><?php echo buildSelect('videoFormat', $videoFormats) ?></td>
</tr> </tr>
<tr> <tr>
<th scope="row"><?php echo translate('FrameRate') ?></th> <th scope="row"><?php echo translate('FrameRate') ?></th>
<td><?php echo buildSelect( "rate", $rates ) ?></td> <td><?php echo buildSelect('rate', $rates) ?></td>
</tr> </tr>
<tr> <tr>
<th scope="row"><?php echo translate('VideoSize') ?></th> <th scope="row"><?php echo translate('VideoSize') ?></th>
<td><?php echo buildSelect( "scale", $scales ) ?></td> <td><?php echo buildSelect('scale', $scales) ?></td>
</tr> </tr>
<tr> <tr>
<th scope="row"><?php echo translate('OverwriteExisting') ?></th> <th scope="row"><?php echo translate('OverwriteExisting') ?></th>
@ -148,11 +150,17 @@ if ( isset($_REQUEST['showIndex']) ) {
<?php <?php
if ( isset($_REQUEST['generated']) ) { 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 <?php
} else { } 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 <?php
} }
?> ?>
@ -164,7 +172,7 @@ if ( isset($_REQUEST['showIndex']) ) {
<?php <?php
} else { } else {
?> ?>
<table id="videoTable" class="major" cellspacing="0"> <table id="videoTable" class="major">
<thead> <thead>
<tr> <tr>
<th scope="row"><?php echo translate('Format') ?></th> <th scope="row"><?php echo translate('Format') ?></th>
@ -184,11 +192,11 @@ if ( isset($_REQUEST['showIndex']) ) {
$rate = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) ); $rate = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) );
$rateText = isset($rates[$rate])?$rates[$rate]:($rate."x"); $rateText = isset($rates[$rate])?$rates[$rate]:($rate."x");
} elseif ( preg_match('/^F(.+)$/', $matches[2], $temp_matches) ) { } elseif ( preg_match('/^F(.+)$/', $matches[2], $temp_matches) ) {
$rateText = $temp_matches[1]."fps"; $rateText = $temp_matches[1].'fps';
} }
if ( preg_match('/^s(.+)$/', $matches[3], $temp_matches) ) { if ( preg_match('/^s(.+)$/', $matches[3], $temp_matches) ) {
$scale = (int)(100 * preg_replace('/_/', '.', $temp_matches[1]) ); $scale = (int)(100 * preg_replace('/_/', '.', $temp_matches[1]) );
$scaleText = isset($scales[$scale])?$scales[$scale]:($scale."x"); $scaleText = isset($scales[$scale])?$scales[$scale]:($scale.'x');
} elseif ( preg_match('/^S(.+)$/', $matches[3], $temp_matches) ) { } elseif ( preg_match('/^S(.+)$/', $matches[3], $temp_matches) ) {
$scaleText = $temp_matches[1]; $scaleText = $temp_matches[1];
} }

View File

@ -85,7 +85,13 @@ if ( empty($_REQUEST['path']) ) {
$Frame->Delta(1); $Frame->Delta(1);
$Frame->FrameId('snapshot'); $Frame->FrameId('snapshot');
} }
$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'; $path = $Event->Path().'/snapshot.jpg';
}
} else { } else {
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'FrameId'=>$_REQUEST['fid'])); $Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'FrameId'=>$_REQUEST['fid']));