Merge branch 'storageareas' of github.com:connortechnology/ZoneMinder into storageareas
This commit is contained in:
commit
cae2c9e237
|
@ -63,7 +63,7 @@ DROP TABLE IF EXISTS `Controls`;
|
|||
CREATE TABLE `Controls` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`Type` enum('Local','Remote','Ffmpeg','Libvlc','cURL') NOT NULL default 'Local',
|
||||
`Type` enum('Local','Remote','Ffmpeg','Libvlc','cURL','WebSite') NOT NULL default 'Local',
|
||||
`Protocol` varchar(64) default NULL,
|
||||
`CanWake` tinyint(3) unsigned NOT NULL default '0',
|
||||
`CanSleep` tinyint(3) unsigned NOT NULL default '0',
|
||||
|
@ -892,7 +892,7 @@ INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES ('4 Wide', '{ "default":{
|
|||
INSERT INTO MontageLayouts (`Name`,`Positions`) VALUES ('5 Wide', '{ "default":{"float":"left", "width":"19%","left":"0px","right":"0px","top":"0px","bottom":"0px"} }' );
|
||||
|
||||
-- We generally don't alter triggers, we drop and re-create them, so let's keep them in a separate file that we can just source in update scripts.
|
||||
source @ZM_PATH_DATA@/db/triggers.sql
|
||||
source @PKGDATADIR@/db/triggers.sql
|
||||
--
|
||||
-- Apply the initial configuration
|
||||
--
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
--
|
||||
-- This updates a 1.31.42 database to 1.31.43
|
||||
--
|
||||
-- Add WebSite enum to Monitor.Type
|
||||
-- Add Refresh column to Monitors table
|
||||
--
|
||||
|
||||
ALTER TABLE `zm`.`Monitors`
|
||||
CHANGE COLUMN `Type` `Type` ENUM('Local', 'Remote', 'File', 'Ffmpeg', 'Libvlc', 'cURL', 'WebSite') NOT NULL DEFAULT 'Local' ;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = 'Monitors'
|
||||
AND table_schema = DATABASE()
|
||||
AND column_name = 'Refresh'
|
||||
) > 0,
|
||||
"SELECT 'Column Refresh exists in Monitors'",
|
||||
"ALTER TABLE Monitors ADD `Refresh` int(10) unsigned default NULL"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.31.42
|
||||
Version: 1.31.43
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
|
|
@ -54,7 +54,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,liburi-encode-perl
|
||||
,libwww-perl
|
||||
,libdata-uuid-perl
|
||||
,libnumber-bytes-human
|
||||
,libnumber-bytes-human-perl
|
||||
,libfile-slurp-perl
|
||||
,mysql-client | virtual-mysql-client
|
||||
,perl-modules
|
||||
|
|
|
@ -71,6 +71,7 @@ The 1.2 at the start is basically adding 20% on top of the calculation to accoun
|
|||
|
||||
The math breakdown for 4 cameras running at 1280x960 capture, 50 frame buffer, 24 bit color space:
|
||||
::
|
||||
|
||||
1280*960 = 1,228,800 (bytes)
|
||||
1,228,800 * (3 bytes for 24 bit) = 3,686,400 (bytes)
|
||||
3,686,400 * 50 = 184,320,000 (bytes)
|
||||
|
|
|
@ -14,7 +14,7 @@ If you are using an older version of ZoneMinder, please follow the legacy steps
|
|||
|
||||
**Step 2:** Mount your dedicated drive, partition, or network share to the local filesystem in any folder of your choosing.
|
||||
We recommend you use systemd to manage the mount points.
|
||||
Instructions on how to accomplish this can be found `here <https://zoneminder.blogspot.com/p/blog-page.html>`_ and `here <https://wiki.zoneminder.com/Common_Issues_with_Zoneminder_Installation_on_Ubuntu#Use_Systemd_to_Mount_Internal_Drive_or_NAS>`_.
|
||||
Instructions on how to accomplish this can be found `here <https://zoneminder.blogspot.com/p/blog-page.html>`__ and `here <https://wiki.zoneminder.com/Common_Issues_with_Zoneminder_Installation_on_Ubuntu#Use_Systemd_to_Mount_Internal_Drive_or_NAS>`__.
|
||||
Note that bind mounting ZoneMinder's images folder is optional. Newer version of ZoneMinder write very little, if anything, to the images folder.
|
||||
Verify the dedicated drive, partition, or network share is successfully mounted before proceeding to the next step.
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ The following notes are based on real problems which have occurred by those who
|
|||
How to Install ZoneMinder
|
||||
-------------------------
|
||||
|
||||
ZoneMinder releases are now being hosted at RPM Fusion. New users should navigate the `RPM Fusion site <https://rpmfusion.org>`_ then follow the instructions to enable that repo. RHEL/CentOS users must also navaigate to the `EPEL Site <https://fedoraproject.org/wiki/EPEL>`_ and enable that repo as well. Once enabled, install ZoneMinder from the commandline:
|
||||
ZoneMinder releases are now being hosted at RPM Fusion. New users should navigate the `RPM Fusion site <https://rpmfusion.org>`__ then follow the instructions to enable that repo. RHEL/CentOS users must also navaigate to the `EPEL Site <https://fedoraproject.org/wiki/EPEL>`_ and enable that repo as well. Once enabled, install ZoneMinder from the commandline:
|
||||
|
||||
::
|
||||
|
||||
|
@ -65,9 +65,9 @@ The feedback we get from those who use these development packages is extremely h
|
|||
How to Change from Zmrepo to RPM Fusion
|
||||
---------------------------------------
|
||||
|
||||
As mentioned above, the place to get the latest ZoneMinder release is now `RPM Fusion <https://rpmfusion.org>`_. If you are currently using ZoneMinder release packages from Zmrepo, then the following steps will change you over to RPM Fusion:
|
||||
As mentioned above, the place to get the latest ZoneMinder release is now `RPM Fusion <https://rpmfusion.org>`__. If you are currently using ZoneMinder release packages from Zmrepo, then the following steps will change you over to RPM Fusion:
|
||||
|
||||
- Navigate to the `RPM Fusion site <https://rpmfusion.org>`_ and enable RPM Fusion on your system
|
||||
- Navigate to the `RPM Fusion site <https://rpmfusion.org>`__ and enable RPM Fusion on your system
|
||||
- Now issue the following from the command line:
|
||||
|
||||
::
|
||||
|
@ -123,7 +123,7 @@ Your build environment is now set up.
|
|||
|
||||
Build from SRPM
|
||||
***************
|
||||
To continue, you need a ZoneMinder SRPM. If you wish to rebuild a ZoneMinder release, then browse the `RPM Fusion site <https://rpmfusion.org/>`_. If instead you wish to rebuild the latest source rpm from our master branch then browse the `Zmrepo site <http://zmrepo.zoneminder.com/>`_.
|
||||
To continue, you need a ZoneMinder SRPM. If you wish to rebuild a ZoneMinder release, then browse the `RPM Fusion site <https://rpmfusion.org/>`__. If instead you wish to rebuild the latest source rpm from our master branch then browse the `Zmrepo site <http://zmrepo.zoneminder.com/>`_.
|
||||
|
||||
For this example, I'll use one of the source rpms from zmrepo:
|
||||
|
||||
|
|
|
@ -147,6 +147,23 @@ Keep aspect ratio
|
|||
Orientation
|
||||
As per local devices.
|
||||
|
||||
WebSite
|
||||
^^^^^^^
|
||||
|
||||
This Source Type allows one to configure an arbitrary website as a non-reocrdable, fully interactive, monitor in ZoneMinder. Note that sites with self-signed certificates will not display until the end user first manually navigates to the site and accpets the unsigned certificate. Also note that some sites will set an X-Frame option in the header, which discourages their site from being displayed within a frame. ZoneMinder will detect this condition and present a warning in the log. When this occurs, the end user can choose to install a browser plugin or extension to workaround this issue.
|
||||
|
||||
Website URL
|
||||
Enter the full http or https url to the desired website.
|
||||
|
||||
Width (pixels)
|
||||
Chose a desired width in pixels that gives an acceptable appearance. This may take some expirimentation.
|
||||
|
||||
Height (pixels)
|
||||
Chose a desired height in pixels that gives an acceptable appearance. This may take some expirimentation.
|
||||
|
||||
Web Site Refresh
|
||||
If the website in question has static content, optionally enter a time period in seconds for ZoneMinder to refresh the content.
|
||||
|
||||
Timestamp Tab
|
||||
-------------
|
||||
|
||||
|
|
|
@ -2946,6 +2946,23 @@ our @options = (
|
|||
type => $types{boolean},
|
||||
category => 'web',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_XFRAME_WARN',
|
||||
default => 'yes',
|
||||
description => 'Warn when website X-Frame-Options is set to sameorigin',
|
||||
help => q`
|
||||
When creating a Web Site monitor, if the target web site has
|
||||
X-Frame-Options set to sameorigin in the header, the site will
|
||||
not display in ZoneMinder. This is a design feature in most modern
|
||||
browsers. When this condiction has occured, ZoneMinder will write a
|
||||
warning to the log file. To get around this, one can install a browser
|
||||
plugin or extension to ignore X-Frame headers, and then the page will
|
||||
display properly. Once the plugin or extenstion has ben installed,
|
||||
the end user may choose to turn this warning off.
|
||||
`,
|
||||
type => $types{boolean},
|
||||
category => 'web',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_H_REFRESH_MAIN',
|
||||
default => '60',
|
||||
|
|
|
@ -77,39 +77,39 @@ sub zmDbConnect {
|
|||
}
|
||||
my $options = shift;
|
||||
|
||||
if ( ( ! defined( $dbh ) ) or ! $dbh->ping() ) {
|
||||
if ( ( !defined($dbh) ) or ! $dbh->ping() ) {
|
||||
my ( $host, $portOrSocket ) = ( $ZoneMinder::Config::Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
|
||||
my $socket;
|
||||
|
||||
if ( defined($portOrSocket) ) {
|
||||
if ( $portOrSocket =~ /^\// ) {
|
||||
$socket = ";mysql_socket=".$portOrSocket;
|
||||
$socket = ';mysql_socket='.$portOrSocket;
|
||||
} else {
|
||||
$socket = ";host=".$host.";port=".$portOrSocket;
|
||||
$socket = ';host='.$host.';port='.$portOrSocket;
|
||||
}
|
||||
} else {
|
||||
$socket = ";host=".$Config{ZM_DB_HOST};
|
||||
$socket = ';host='.$Config{ZM_DB_HOST};
|
||||
}
|
||||
|
||||
my $sslOptions = "";
|
||||
my $sslOptions = '';
|
||||
if ( $Config{ZM_DB_SSL_CA_CERT} ) {
|
||||
$sslOptions = ';'.join(';',
|
||||
"mysql_ssl=1",
|
||||
"mysql_ssl_ca_file=".$Config{ZM_DB_SSL_CA_CERT},
|
||||
"mysql_ssl_client_key=".$Config{ZM_DB_SSL_CLIENT_KEY},
|
||||
"mysql_ssl_client_cert=".$Config{ZM_DB_SSL_CLIENT_CERT}
|
||||
'mysql_ssl=1',
|
||||
'mysql_ssl_ca_file='.$Config{ZM_DB_SSL_CA_CERT},
|
||||
'mysql_ssl_client_key='.$Config{ZM_DB_SSL_CLIENT_KEY},
|
||||
'mysql_ssl_client_cert='.$Config{ZM_DB_SSL_CLIENT_CERT}
|
||||
);
|
||||
}
|
||||
|
||||
$dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME}
|
||||
$dbh = DBI->connect( 'DBI:mysql:database='.$Config{ZM_DB_NAME}
|
||||
.$socket . $sslOptions . ($options?';'.join(';', map { $_.'='.$$options{$_} } keys %{$options} ) : '' )
|
||||
, $Config{ZM_DB_USER}
|
||||
, $Config{ZM_DB_PASS}
|
||||
);
|
||||
$dbh->trace( 0 );
|
||||
$dbh->trace(0) if $dbh;
|
||||
}
|
||||
return( $dbh );
|
||||
}
|
||||
return $dbh;
|
||||
} # end sub zmDbConnect
|
||||
|
||||
sub zmDbDisconnect {
|
||||
if ( defined( $dbh ) ) {
|
||||
|
|
|
@ -529,6 +529,8 @@ sub MoveTo {
|
|||
my ( $NewPath ) = ( $NewStorage->Path() =~ /^(.*)$/ ); # De-taint
|
||||
if ( ! $$NewStorage{Id} ) {
|
||||
return "New storage does not have an id. Moving will not happen.";
|
||||
} elsif ( $$NewStorage{Id} == $$self{StorageId} ) {
|
||||
return "Event is already located at " . $NewPath;
|
||||
} elsif ( !$NewPath ) {
|
||||
return "New path ($NewPath) is empty.";
|
||||
} elsif ( ! -e $NewPath ) {
|
||||
|
|
|
@ -160,9 +160,12 @@ sub Sql {
|
|||
if ( $term->{attr} =~ /^Monitor/ ) {
|
||||
my ( $temp_attr_name ) = $term->{attr} =~ /^Monitor(.+)$/;
|
||||
$self->{Sql} .= 'M.'.$temp_attr_name;
|
||||
} elsif ( $term->{attr} =~ /^Server/ ) {
|
||||
$self->{Sql} .= 'S.'.$term->{attr};
|
||||
|
||||
} elsif ( $term->{attr} eq 'ServerId' or $term->{attr} eq 'MonitorServerId' ) {
|
||||
$self->{Sql} .= 'M.ServerId';
|
||||
} elsif ( $term->{attr} eq 'StorageServerId' ) {
|
||||
$self->{Sql} .= 'S.ServerId';
|
||||
} elsif ( $term->{attr} eq 'FilterServerId' ) {
|
||||
$self->{Sql} .= $Config{ZM_SERVER_ID};
|
||||
# StartTime options
|
||||
} elsif ( $term->{attr} eq 'DateTime' ) {
|
||||
$self->{Sql} .= 'E.StartTime';
|
||||
|
@ -208,7 +211,7 @@ sub Sql {
|
|||
foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) {
|
||||
if ( $term->{attr} =~ /^MonitorName/ ) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} eq 'ServerId' ) {
|
||||
} elsif ( $term->{attr} =~ /ServerId/) {
|
||||
Debug("ServerId, temp_value is ($temp_value) ($ZoneMinder::Config::Config{ZM_SERVER_ID})");
|
||||
if ( $temp_value eq 'ZM_SERVER_ID' ) {
|
||||
$value = "'$ZoneMinder::Config::Config{ZM_SERVER_ID}'";
|
||||
|
|
|
@ -158,6 +158,7 @@ sub new {
|
|||
( $this->{fileName} = $0 ) =~ s|^.*/||;
|
||||
$this->{logPath} = $Config{ZM_PATH_LOGS};
|
||||
$this->{logFile} = $this->{logPath}.'/'.$this->{id}.'.log';
|
||||
($this->{logFile}) = $this->{logFile} =~ /^([\w\.\/]+)$/;
|
||||
|
||||
$this->{trace} = 0;
|
||||
|
||||
|
@ -207,6 +208,7 @@ sub initialise( @ ) {
|
|||
if ( my $logFile = $this->getTargettedEnv('LOG_FILE') ) {
|
||||
$tempLogFile = $logFile;
|
||||
}
|
||||
($tempLogFile) = $tempLogFile =~ /^([\w\.\/]+)$/;
|
||||
|
||||
my $tempLevel = INFO;
|
||||
my $tempTermLevel = $this->{termLevel};
|
||||
|
@ -581,7 +583,11 @@ sub logPrint {
|
|||
syslog($priorities{$level}, $code.' [%s]', $string);
|
||||
}
|
||||
print($LOGFILE $message) if $level <= $this->{fileLevel};
|
||||
print(STDERR $message) if $level <= $this->{termLevel};
|
||||
|
||||
if ( $level <= $this->{databaseLevel} ) {
|
||||
if ( ( $this->{dbh} and $this->{dbh}->ping() ) or ( $this->{dbh} = zmDbConnect() ) ) {
|
||||
|
||||
my $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NULL )';
|
||||
$this->{sth} = $this->{dbh}->prepare_cached($sql);
|
||||
if ( !$this->{sth} ) {
|
||||
|
@ -598,11 +604,13 @@ sub logPrint {
|
|||
);
|
||||
if ( !$res ) {
|
||||
$this->{databaseLevel} = NOLOG;
|
||||
Error("Can't execute log entry '$sql': ".$this->{sth}->errstr());
|
||||
Error("Can't execute log entry '$sql': ".$this->{dbh}->errstr());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print(STDERR "Can't log to database: ");
|
||||
}
|
||||
} # end if doing db logging
|
||||
print(STDERR $message) if $level <= $this->{termLevel};
|
||||
} # end if level < effectivelevel
|
||||
}
|
||||
|
||||
|
|
|
@ -242,6 +242,7 @@ use constant KILL_DELAY => 60; # seconds to wait between sending TERM and sendin
|
|||
our %cmd_hash;
|
||||
our %pid_hash;
|
||||
our %terminating_processes;
|
||||
our $zm_terminate = 0;
|
||||
|
||||
sub run {
|
||||
my $fd = 0;
|
||||
|
@ -276,9 +277,9 @@ sub run {
|
|||
listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
|
||||
|
||||
$SIG{CHLD} = \&reaper;
|
||||
$SIG{INT} = \&shutdownAll;
|
||||
$SIG{TERM} = \&shutdownAll;
|
||||
$SIG{ABRT} = \&shutdownAll;
|
||||
$SIG{INT} = \&shutdown_sig_handler;
|
||||
$SIG{TERM} = \&shutdown_sig_handler;
|
||||
$SIG{ABRT} = \&shutdown_sig_handler;
|
||||
$SIG{HUP} = \&logrot;
|
||||
|
||||
my $rin = '';
|
||||
|
@ -295,12 +296,17 @@ sub run {
|
|||
dPrint(ZoneMinder::Logger::INFO, 'Loading Server record have ' . $$Server{Name});
|
||||
}
|
||||
|
||||
while( 1 ) {
|
||||
while( !$zm_terminate ) {
|
||||
|
||||
if ( $Config{ZM_SERVER_ID} ) {
|
||||
if ( ! ( $secs_count % 60 ) ) {
|
||||
$dbh = zmDbConnect() if ! $dbh->ping();
|
||||
Debug("Connecting");
|
||||
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
|
||||
Warning("Not connected to db ($dbh). Reconnecting");
|
||||
$dbh = zmDbConnect();
|
||||
}
|
||||
my @cpuload = CpuLoad();
|
||||
Debug("UPdating Server record @cpuload");
|
||||
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} ) ) {
|
||||
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr());
|
||||
|
@ -308,7 +314,9 @@ sub run {
|
|||
}
|
||||
$secs_count += 1;
|
||||
}
|
||||
Debug("Before select");
|
||||
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);
|
||||
|
@ -330,7 +338,8 @@ sub run {
|
|||
# Do nothing, this is all we're here for
|
||||
dPrint(ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n");
|
||||
} elsif ( $command eq 'shutdown' ) {
|
||||
shutdownAll();
|
||||
# Breka out of while loop
|
||||
last;
|
||||
} elsif ( $command eq 'check' ) {
|
||||
check($daemon, @args);
|
||||
} elsif ( $command eq 'status' ) {
|
||||
|
@ -346,14 +355,13 @@ sub run {
|
|||
}
|
||||
close(CLIENT);
|
||||
} else {
|
||||
Fatal('Bogus descriptor');
|
||||
Error('Bogus descriptor');
|
||||
}
|
||||
} elsif ( $nfound < 0 ) {
|
||||
if ( $! == EINTR ) {
|
||||
# Dead child, will be reaped
|
||||
#print( "Probable dead child\n" );
|
||||
# See if it needs to start up again
|
||||
restartPending();
|
||||
} elsif ( $! == EPIPE ) {
|
||||
Error("Can't select: $!");
|
||||
} else {
|
||||
|
@ -361,12 +369,15 @@ sub run {
|
|||
}
|
||||
} else {
|
||||
#print( "Select timed out\n" );
|
||||
restartPending();
|
||||
}
|
||||
|
||||
Debug("restartPending");
|
||||
restartPending();
|
||||
Debug("check_for_processes_to_kill");
|
||||
check_for_processes_to_kill();
|
||||
|
||||
} # end while
|
||||
|
||||
dPrint(ZoneMinder::Logger::INFO, 'Server exiting at '
|
||||
.strftime( '%y/%m/%d %H:%M:%S', localtime() )
|
||||
."\n"
|
||||
|
@ -377,9 +388,7 @@ sub run {
|
|||
Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr());
|
||||
}
|
||||
}
|
||||
unlink(main::SOCK_FILE) or Error('Unable to unlink ' . main::SOCK_FILE .". Error message was: $!") if ( -e main::SOCK_FILE );
|
||||
unlink(ZM_PID) or Error('Unable to unlink ' . ZM_PID .". Error message was: $!") if ( -e ZM_PID );
|
||||
exit();
|
||||
shutdownAll();
|
||||
}
|
||||
|
||||
sub cPrint {
|
||||
|
@ -426,10 +435,12 @@ sub start {
|
|||
}
|
||||
|
||||
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: $!");
|
||||
Debug("forking");
|
||||
if ( my $cpid = fork() ) {
|
||||
logReinit();
|
||||
#logReinit();
|
||||
|
||||
$process->{pid} = $cpid;
|
||||
$process->{started} = time();
|
||||
|
@ -442,6 +453,7 @@ sub start {
|
|||
|
||||
$cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process;
|
||||
sigprocmask(SIG_SETMASK, $sigset) or Fatal("Can't restore SIGCHLD: $!");
|
||||
Debug("unblocko child");
|
||||
} elsif ( defined($cpid) ) {
|
||||
# Force reconnection to the db.
|
||||
$dbh = zmDbConnect(1);
|
||||
|
@ -527,16 +539,18 @@ sub check_for_processes_to_kill {
|
|||
my $sigset = POSIX::SigSet->new;
|
||||
my $blockset = POSIX::SigSet->new(SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, $blockset, $sigset) or die "dying at block...\n";
|
||||
foreach my $command ( %terminating_processes ) {
|
||||
foreach my $command ( keys %terminating_processes ) {
|
||||
my $process = $cmd_hash{$command};
|
||||
Debug("Have process $command at pid $$process{pid} $$process{term_sent_at}");
|
||||
if ( $$process{term_sent_at} - time > KILL_DELAY ) {
|
||||
my $now = time;
|
||||
Debug("Have process $command at pid $$process{pid} $$process{term_sent_at} - $now = " . ( $$process{term_sent_at} - $now ) );
|
||||
if ( $$process{term_sent_at} and ( $$process{term_sent_at} - $now > KILL_DELAY ) ) {
|
||||
dPrint(ZoneMinder::Logger::WARNING, "'$$process{command}' has not stopped at "
|
||||
.strftime('%y/%m/%d %H:%M:%S', localtime())
|
||||
.' after ' . KILL_DELAY . ' seconds.'
|
||||
." Sending KILL to pid $$process{pid}\n"
|
||||
);
|
||||
kill('KILL', $$process{pid});
|
||||
delete $terminating_processes{$command};
|
||||
}
|
||||
}
|
||||
sigprocmask(SIG_UNBLOCK, $blockset) or die "dying at unblock...\n";
|
||||
|
@ -595,8 +609,14 @@ sub logrot {
|
|||
}
|
||||
}
|
||||
|
||||
sub shutdown_sig_handler {
|
||||
$zm_terminate = 1;
|
||||
}
|
||||
|
||||
sub reaper {
|
||||
my $saved_status = $!;
|
||||
|
||||
# Wait for a child to terminate
|
||||
while ( (my $cpid = waitpid(-1, WNOHANG)) > 0 ) {
|
||||
my $status = $?;
|
||||
|
||||
|
@ -620,8 +640,8 @@ sub reaper {
|
|||
|
||||
my $out_str = "'$process->{command}' ";
|
||||
if ( $exit_signal ) {
|
||||
# 15 == TERM, 14 == ALARM
|
||||
if ( $exit_signal == 15 || $exit_signal == 14 ) {
|
||||
# TERM or ALRM
|
||||
$out_str .= 'exited';
|
||||
} else {
|
||||
$out_str .= 'crashed';
|
||||
|
@ -659,22 +679,26 @@ sub reaper {
|
|||
$process->{delay} = $Config{ZM_MAX_RESTART_DELAY};
|
||||
}
|
||||
}
|
||||
Debug("Delay for $$process{command} is now $$process{delay}");
|
||||
} else {
|
||||
delete $cmd_hash{$$process{command}};
|
||||
}
|
||||
}
|
||||
} # end while waitpid
|
||||
$SIG{CHLD} = \&reaper;
|
||||
$! = $saved_status;
|
||||
Debug("Leaving reaper");
|
||||
}
|
||||
|
||||
sub restartPending {
|
||||
# Restart any pending processes
|
||||
foreach my $process ( values( %cmd_hash ) ) {
|
||||
# Restart any pending processes, we list them first because cmd_hash may change in foreach
|
||||
my @processes = values %cmd_hash;
|
||||
foreach my $process ( @processes ) {
|
||||
if ( $process->{pending} && $process->{pending} <= time() ) {
|
||||
dPrint(ZoneMinder::Logger::INFO, "Starting pending process, $process->{command}\n");
|
||||
start($process->{daemon}, @{$process->{args}});
|
||||
}
|
||||
}
|
||||
dPrint(ZoneMinder::Logger::INFO, "done restartPending");
|
||||
}
|
||||
|
||||
sub shutdownAll {
|
||||
|
@ -683,9 +707,14 @@ sub shutdownAll {
|
|||
next if ! $pid_hash{$pid};
|
||||
send_stop(1, $pid_hash{$pid});
|
||||
}
|
||||
while ( %terminating_processes ) {
|
||||
my $count= KILL_DELAY;
|
||||
while ( (keys %terminating_processes) and $count) {
|
||||
check_for_processes_to_kill();
|
||||
sleep(1) if %terminating_processes;
|
||||
if ( %terminating_processes ) {
|
||||
Debug("Still " . %terminating_processes . ' to die. count is: ' . $count . ' sleeping');
|
||||
sleep(1);
|
||||
$count --;
|
||||
}
|
||||
}
|
||||
dPrint(ZoneMinder::Logger::INFO, "Server shutdown at "
|
||||
.strftime('%y/%m/%d %H:%M:%S', localtime())
|
||||
|
|
|
@ -94,7 +94,7 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|)
|
|||
: ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS})
|
||||
;
|
||||
|
||||
logInit();
|
||||
logInit($filter_id?(id=>'zmfilter_'.$filter_id):());
|
||||
sub HupHandler {
|
||||
Info("Received HUP, reloading");
|
||||
&ZoneMinder::Logger::logHupHandler();
|
||||
|
@ -154,38 +154,38 @@ my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL};
|
|||
my $event_id = 0;
|
||||
|
||||
if ( ! EVENT_PATH ) {
|
||||
Error( "No event path defined. Config was $Config{ZM_DIR_EVENTS}\n" );
|
||||
Error("No event path defined. Config was $Config{ZM_DIR_EVENTS}\n");
|
||||
die;
|
||||
}
|
||||
|
||||
# In future, should not be neccessary wrt StorageAreas
|
||||
chdir( EVENT_PATH );
|
||||
|
||||
# SHould not be neccessary... but nice to get a local var. What if it fails?
|
||||
# Should not be neccessary... but nice to get a local var. What if it fails?
|
||||
my $dbh = zmDbConnect();
|
||||
|
||||
if ( $filter_name ) {
|
||||
Info( "Scanning for events using filter '$filter_name'\n" );
|
||||
Info("Scanning for events using filter '$filter_name'\n");
|
||||
} elsif ( $filter_id ) {
|
||||
Info( "Scanning for events using filter id '$filter_id'\n" );
|
||||
Info("Scanning for events using filter id '$filter_id'\n");
|
||||
} else {
|
||||
Info( "Scanning for events using all filters\n" );
|
||||
Info("Scanning for events using all filters\n");
|
||||
}
|
||||
|
||||
if ( ! ( $filter_name or $filter_id ) ) {
|
||||
Debug("Sleeping due to start delay: " . START_DELAY . ' seconds...' );
|
||||
sleep( START_DELAY );
|
||||
Debug("Sleeping due to start delay: " . START_DELAY . ' seconds...');
|
||||
sleep(START_DELAY);
|
||||
}
|
||||
|
||||
my @filters;
|
||||
my $last_action = 0;
|
||||
|
||||
while( ! $zm_terminate ) {
|
||||
while( !$zm_terminate ) {
|
||||
my $now = time;
|
||||
if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) {
|
||||
Debug( "Reloading filters\n" );
|
||||
Debug("Reloading filters\n");
|
||||
$last_action = $now;
|
||||
@filters = getFilters( { Name=>$filter_name, Id=>$filter_id } );
|
||||
@filters = getFilters({ Name=>$filter_name, Id=>$filter_id });
|
||||
}
|
||||
|
||||
foreach my $filter ( @filters ) {
|
||||
|
@ -195,16 +195,16 @@ while( ! $zm_terminate ) {
|
|||
my ( $id ) = $$filter{Id} =~ /(\d+)/;
|
||||
Debug("Running concurrent filter process $proc --filter_id $$filter{Id} => $id for $$filter{Name}");
|
||||
|
||||
system( qq`$proc --filter "$$filter{Name}" &` );
|
||||
system(qq`$proc --filter "$$filter{Name}" &`);
|
||||
} else {
|
||||
checkFilter( $filter );
|
||||
checkFilter($filter);
|
||||
}
|
||||
}
|
||||
|
||||
last if $filter_name or $filter_id or $zm_terminate;
|
||||
|
||||
Debug( "Sleeping for $delay seconds\n" );
|
||||
sleep( $delay );
|
||||
Debug("Sleeping for $delay seconds\n");
|
||||
sleep($delay);
|
||||
}
|
||||
|
||||
sub getFilters {
|
||||
|
@ -232,18 +232,18 @@ sub getFilters {
|
|||
or UpdateDiskSpace = 1
|
||||
or AutoMove = 1
|
||||
) ORDER BY Name';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable to prepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( @sql_values )
|
||||
or Fatal( "Unable to execute '$sql': ".$sth->errstr() );
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
or Fatal("Unable to prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute(@sql_values)
|
||||
or Fatal("Unable to execute '$sql': ".$dbh->errstr());
|
||||
FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) {
|
||||
my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter );
|
||||
Debug( "Found filter '$db_filter->{Name}'\n" );
|
||||
my $filter = new ZoneMinder::Filter($$db_filter{Id}, $db_filter);
|
||||
Debug("Found filter '$db_filter->{Name}'");
|
||||
# The undef here is to make sure the Sql gets regenerated because the Filter object may be cached
|
||||
my $filter_sql = $filter->Sql(undef);
|
||||
|
||||
if ( ! $filter_sql ) {
|
||||
Error( "Error parsing Sql. skipping filter '$db_filter->{Name}'\n" );
|
||||
Error("Error parsing Sql. skipping filter '$db_filter->{Name}'");
|
||||
next FILTER;
|
||||
}
|
||||
push @filters, $filter;
|
||||
|
@ -252,7 +252,7 @@ FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) {
|
|||
if ( ! @filters ) {
|
||||
Warning("No filter found for $sql with values(@sql_values)");
|
||||
} else {
|
||||
Debug( "Got " . @filters . " filters" );
|
||||
Debug("Got " . @filters . " filters");
|
||||
}
|
||||
|
||||
return @filters;
|
||||
|
@ -283,56 +283,56 @@ sub checkFilter {
|
|||
|
||||
foreach my $event ( @Events ) {
|
||||
last if $zm_terminate;
|
||||
my $Event = new ZoneMinder::Event( $$event{Id}, $event );
|
||||
my $Event = new ZoneMinder::Event($$event{Id}, $event);
|
||||
|
||||
Debug( "Checking event $event->{Id}" );
|
||||
Debug("Checking event $event->{Id}");
|
||||
my $delete_ok = !undef;
|
||||
$dbh->ping();
|
||||
if ( $filter->{AutoArchive} ) {
|
||||
Info( "Archiving event $event->{Id}" );
|
||||
Info("Archiving event $event->{Id}");
|
||||
# Do it individually to avoid locking up the table for new events
|
||||
my $sql = 'UPDATE Events SET Archived = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal("Unable to prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Error( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
or Error("Unable to execute '$sql': ".$dbh->errstr());
|
||||
}
|
||||
if ( $Config{ZM_OPT_FFMPEG} && $filter->{AutoVideo} ) {
|
||||
if ( !$event->{Videoed} ) {
|
||||
$delete_ok = undef if ( !generateVideo( $filter, $event ) );
|
||||
$delete_ok = undef if !generateVideo($filter, $event);
|
||||
}
|
||||
}
|
||||
if ( $Config{ZM_OPT_EMAIL} && $filter->{AutoEmail} ) {
|
||||
if ( !$event->{Emailed} ) {
|
||||
$delete_ok = undef if ( !sendEmail( $filter, $Event ) );
|
||||
$delete_ok = undef if !sendEmail($filter, $Event);
|
||||
}
|
||||
}
|
||||
if ( $Config{ZM_OPT_MESSAGE} && $filter->{AutoMessage} ) {
|
||||
if ( !$event->{Messaged} ) {
|
||||
$delete_ok = undef if ( !sendMessage( $filter, $event ) );
|
||||
$delete_ok = undef if !sendMessage($filter, $event);
|
||||
}
|
||||
}
|
||||
if ( $Config{ZM_OPT_UPLOAD} && $filter->{AutoUpload} ) {
|
||||
if ( !$event->{Uploaded} ) {
|
||||
$delete_ok = undef if ( !uploadArchFile( $filter, $event ) );
|
||||
$delete_ok = undef if !uploadArchFile($filter, $event);
|
||||
}
|
||||
}
|
||||
if ( $filter->{AutoExecute} ) {
|
||||
if ( !$event->{Executed} ) {
|
||||
$delete_ok = undef if ( !executeCommand( $filter, $event ) );
|
||||
$delete_ok = undef if !executeCommand($filter, $event);
|
||||
}
|
||||
}
|
||||
if ( $filter->{AutoDelete} ) {
|
||||
if ( $delete_ok ) {
|
||||
$Event->delete();
|
||||
} else {
|
||||
Error( "Unable toto delete event $event->{Id} as previous operations failed\n" );
|
||||
Error("Unable toto delete event $event->{Id} as previous operations failed");
|
||||
}
|
||||
} # end if AutoDelete
|
||||
|
||||
if ( $filter->{AutoMove} ) {
|
||||
my $NewStorage = new ZoneMinder::Storage( $filter->{AutoMoveTo} );
|
||||
$_ = $Event->MoveTo( $NewStorage );
|
||||
my $NewStorage = new ZoneMinder::Storage($filter->{AutoMoveTo});
|
||||
$_ = $Event->MoveTo($NewStorage);
|
||||
Error($_) if $_;
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,7 @@ sub generateVideo {
|
|||
my $scale = $event->{DefaultScale}/100;
|
||||
my $format;
|
||||
|
||||
my @ffmpeg_formats = split( /\s+/, $Config{ZM_FFMPEG_FORMATS} );
|
||||
my @ffmpeg_formats = split(/\s+/, $Config{ZM_FFMPEG_FORMATS});
|
||||
my $default_video_format;
|
||||
my $default_phone_format;
|
||||
foreach my $ffmpeg_format( @ffmpeg_formats ) {
|
||||
|
@ -408,10 +408,10 @@ sub generateVideo {
|
|||
return 0;
|
||||
} else {
|
||||
my $sql = 'UPDATE Events SET Videoed = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable to prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal("Unable toexecute '$sql': ".$sth->errstr());
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
or Fatal("Unable to prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute($event->{Id})
|
||||
or Fatal("Unable toexecute '$sql': ".$dbh->errstr());
|
||||
if ( wantarray() ) {
|
||||
return( $format, $output );
|
||||
}
|
||||
|
@ -463,12 +463,12 @@ sub uploadArchFile {
|
|||
my $event = shift;
|
||||
|
||||
if ( ! $Config{ZM_UPLOAD_HOST} ) {
|
||||
Error( 'Cannot upload archive as no upload host defined' );
|
||||
Error('Cannot upload archive as no upload host defined');
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
my $archFile = $event->{MonitorName}.'-'.$event->{Id};
|
||||
my $archImagePath = getEventPath( $event )
|
||||
my $archImagePath = getEventPath($event)
|
||||
.'/'
|
||||
.(
|
||||
( $Config{ZM_UPLOAD_ARCH_ANALYSE} )
|
||||
|
@ -485,14 +485,14 @@ sub uploadArchFile {
|
|||
$archFile .= '.zip';
|
||||
$archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile;
|
||||
my $zip = Archive::Zip->new();
|
||||
Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" );
|
||||
Info("Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n");
|
||||
|
||||
my $status = &AZ_OK;
|
||||
foreach my $imageFile ( @archImageFiles ) {
|
||||
Debug( "Adding $imageFile\n" );
|
||||
my $member = $zip->addFile( $imageFile );
|
||||
Debug("Adding $imageFile\n");
|
||||
my $member = $zip->addFile($imageFile);
|
||||
if ( !$member ) {
|
||||
Error( "Unable toto add image file $imageFile to zip archive $archLocPath" );
|
||||
Error("Unable toto add image file $imageFile to zip archive $archLocPath");
|
||||
$archError = 1;
|
||||
last;
|
||||
}
|
||||
|
@ -505,10 +505,10 @@ sub uploadArchFile {
|
|||
$status = $zip->writeToFileNamed( $archLocPath );
|
||||
|
||||
if ( $archError = ($status != &AZ_OK) ) {
|
||||
Error( "Zip error: $status\n " );
|
||||
Error("Zip error: $status");
|
||||
}
|
||||
} else {
|
||||
Error( "Error adding images to zip archive $archLocPath, not writing" );
|
||||
Error("Error adding images to zip archive $archLocPath, not writing");
|
||||
}
|
||||
} elsif ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'tar' ) {
|
||||
if ( $Config{ZM_UPLOAD_ARCH_COMPRESS} ) {
|
||||
|
@ -517,7 +517,7 @@ sub uploadArchFile {
|
|||
$archFile .= '.tar';
|
||||
}
|
||||
$archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile;
|
||||
Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" );
|
||||
Info("Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n");
|
||||
|
||||
if ( $archError = !Archive::Tar->create_archive(
|
||||
$archLocPath,
|
||||
|
@ -525,7 +525,7 @@ sub uploadArchFile {
|
|||
@archImageFiles
|
||||
)
|
||||
) {
|
||||
Error( 'Tar error: '.Archive::Tar->error()."\n " );
|
||||
Error('Tar error: '.Archive::Tar->error());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ sub uploadArchFile {
|
|||
return( 0 );
|
||||
} else {
|
||||
if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) {
|
||||
Info( 'Uploading to '.$Config{ZM_UPLOAD_HOST}." using FTP\n" );
|
||||
Info('Uploading to '.$Config{ZM_UPLOAD_HOST}." using FTP");
|
||||
my $ftp = Net::FTP->new(
|
||||
$Config{ZM_UPLOAD_HOST},
|
||||
Timeout=>$Config{ZM_UPLOAD_TIMEOUT},
|
||||
|
@ -541,58 +541,56 @@ sub uploadArchFile {
|
|||
Debug=>$Config{ZM_UPLOAD_DEBUG}
|
||||
);
|
||||
if ( !$ftp ) {
|
||||
Error( "Unable tocreate FTP connection: $@" );
|
||||
return( 0 );
|
||||
Error("Unable tocreate FTP connection: $@");
|
||||
return 0;
|
||||
}
|
||||
$ftp->login( $Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS} )
|
||||
or Error( "FTP - Unable tologin" );
|
||||
$ftp->login($Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS})
|
||||
or Error("FTP - Unable tologin");
|
||||
$ftp->binary()
|
||||
or Error( "FTP - Unable togo binary" );
|
||||
$ftp->cwd( $Config{ZM_UPLOAD_REM_DIR} )
|
||||
or Error( "FTP - Unable tocwd" )
|
||||
or Error("FTP - Unable togo binary");
|
||||
$ftp->cwd($Config{ZM_UPLOAD_REM_DIR})
|
||||
or Error("FTP - Unable tocwd")
|
||||
if ( $Config{ZM_UPLOAD_REM_DIR} );
|
||||
$ftp->put( $archLocPath )
|
||||
or Error( "FTP - Unable toupload '$archLocPath'" );
|
||||
or Error("FTP - Unable toupload '$archLocPath'");
|
||||
$ftp->quit()
|
||||
or Error( "FTP - Unable toquit" );
|
||||
or Error("FTP - Unable toquit");
|
||||
} else {
|
||||
my $host = $Config{ZM_UPLOAD_HOST};
|
||||
$host .= ':'.$Config{ZM_UPLOAD_PORT}
|
||||
if $Config{ZM_UPLOAD_PORT};
|
||||
Info( 'Uploading to '.$host." using SFTP\n" );
|
||||
my %sftpOptions = ( host=>$Config{ZM_UPLOAD_HOST}, user=>$Config{ZM_UPLOAD_USER} );
|
||||
$sftpOptions{password} = $Config{ZM_UPLOAD_PASS}
|
||||
if $Config{ZM_UPLOAD_PASS};
|
||||
$sftpOptions{port} = $Config{ZM_UPLOAD_PORT}
|
||||
if $Config{ZM_UPLOAD_PORT};
|
||||
$sftpOptions{timeout} = $Config{ZM_UPLOAD_TIMEOUT}
|
||||
if $Config{ZM_UPLOAD_TIMEOUT};
|
||||
$host .= ':'.$Config{ZM_UPLOAD_PORT} if $Config{ZM_UPLOAD_PORT};
|
||||
Info('Uploading to '.$host." using SFTP\n");
|
||||
my %sftpOptions = (
|
||||
host=>$Config{ZM_UPLOAD_HOST}, user=>$Config{ZM_UPLOAD_USER}
|
||||
($Config{ZM_UPLOAD_PASS} ? (password=>$Config{ZM_UPLOAD_PASS}) : ()),
|
||||
($Config{ZM_UPLOAD_PORT} ? (port=>$Config{ZM_UPLOAD_PORT}) : ()),
|
||||
($Config{ZM_UPLOAD_TIMEOUT} ? (timeout=>$Config{ZM_UPLOAD_TIMEOUT}) : ()),
|
||||
);
|
||||
my @more_ssh_args;
|
||||
push @more_ssh_args, '-o'=>'StrictHostKeyChecking=no'
|
||||
if ! $Config{ZM_UPLOAD_STRICT};
|
||||
push @more_ssh_args, '-v'
|
||||
if $Config{ZM_UPLOAD_DEBUG};
|
||||
$sftpOptions{more} = [@more_ssh_args];
|
||||
my $sftp = Net::SFTP::Foreign->new( $Config{ZM_UPLOAD_HOST}, %sftpOptions );
|
||||
my $sftp = Net::SFTP::Foreign->new($Config{ZM_UPLOAD_HOST}, %sftpOptions);
|
||||
if ( $sftp->error ) {
|
||||
Error( "Unable tocreate SFTP connection: ".$sftp->error );
|
||||
return( 0 );
|
||||
Error("Unable tocreate SFTP connection: ".$sftp->error);
|
||||
return 0;
|
||||
}
|
||||
$sftp->setcwd( $Config{ZM_UPLOAD_REM_DIR} )
|
||||
or Error( "SFTP - Unable tosetcwd: ".$sftp->error )
|
||||
$sftp->setcwd($Config{ZM_UPLOAD_REM_DIR})
|
||||
or Error("SFTP - Unable to setcwd: ".$sftp->error)
|
||||
if $Config{ZM_UPLOAD_REM_DIR};
|
||||
$sftp->put( $archLocPath, $archFile )
|
||||
or Error( "SFTP - Unable toupload '$archLocPath': ".$sftp->error );
|
||||
$sftp->put($archLocPath, $archFile)
|
||||
or Error("SFTP - Unable to upload '$archLocPath': ".$sftp->error);
|
||||
}
|
||||
unlink( $archLocPath );
|
||||
unlink($archLocPath);
|
||||
my $sql = 'UPDATE Events SET Uploaded = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
or Fatal("Unable toprepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute($event->{Id})
|
||||
or Fatal("Unable toexecute '$sql': ".$dbh->errstr());
|
||||
}
|
||||
return( 1 );
|
||||
}
|
||||
return 1;
|
||||
} # end sub uploadArchFile
|
||||
|
||||
sub substituteTags {
|
||||
my $text = shift;
|
||||
|
@ -613,14 +611,13 @@ sub substituteTags {
|
|||
my $max_alarm_frame;
|
||||
my $max_alarm_score = 0;
|
||||
if ( $need_images ) {
|
||||
my $sql = "SELECT * FROM Frames
|
||||
my $sql = q`SELECT * FROM Frames
|
||||
WHERE EventId = ? AND Type = 'Alarm'
|
||||
ORDER BY FrameId"
|
||||
;
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $Event->{Id} )
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
ORDER BY FrameId`;
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
or Fatal("Unable toprepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute($Event->{Id})
|
||||
or Fatal( "Unable toexecute '$sql': ".$dbh->errstr());
|
||||
my $rows = 0;
|
||||
while( my $frame = $sth->fetchrow_hashref() ) {
|
||||
if ( !$first_alarm_frame ) {
|
||||
|
@ -646,8 +643,8 @@ sub substituteTags {
|
|||
$text =~ s/%MEM%/$Monitor->{MonthEvents}/g;
|
||||
$text =~ s/%MEA%/$Monitor->{ArchivedEvents}/g;
|
||||
$text =~ s/%MP%/$url?view=watch&mid=$Event->{MonitorId}/g;
|
||||
$text =~ s/%MPS%/$url?view=watchfeed&mid=$Event->{MonitorId}&mode=stream/g;
|
||||
$text =~ s/%MPI%/$url?view=watchfeed&mid=$Event->{MonitorId}&mode=still/g;
|
||||
$text =~ s/%MPS%/$url?view=watch&mid=$Event->{MonitorId}&mode=stream/g;
|
||||
$text =~ s/%MPI%/$url?view=watch&mid=$Event->{MonitorId}&mode=still/g;
|
||||
$text =~ s/%EP%/$url?view=event&mid=$Event->{MonitorId}&eid=$Event->{Id}/g;
|
||||
$text =~ s/%EPS%/$url?view=event&mode=stream&mid=$Event->{MonitorId}&eid=$Event->{Id}/g;
|
||||
$text =~ s/%EPI%/$url?view=event&mode=still&mid=$Event->{MonitorId}&eid=$Event->{Id}/g;
|
||||
|
@ -697,13 +694,13 @@ sub substituteTags {
|
|||
if ( $attachments_ref && $text =~ s/%EIMA%//g ) {
|
||||
# Don't attach the same image twice
|
||||
if ( !@$attachments_ref
|
||||
|| ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} )
|
||||
|| ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId})
|
||||
) {
|
||||
my $path = generateImage($Event, $max_alarm_frame, 'analyse');
|
||||
if ( -e $path ) {
|
||||
push @$attachments_ref, { type=>'image/jpeg', path=>$path };
|
||||
} else {
|
||||
Warning("No image for EIMA");
|
||||
Warning('No image for EIMA');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -737,7 +734,7 @@ sub sendEmail {
|
|||
my $Event = shift;
|
||||
|
||||
if ( ! $Config{ZM_FROM_EMAIL} ) {
|
||||
Error("No 'from' email address defined, not sending email");
|
||||
Error('No from email address defined, not sending email');
|
||||
return 0;
|
||||
}
|
||||
if ( ! $Config{ZM_EMAIL_ADDRESS} ) {
|
||||
|
@ -745,7 +742,7 @@ sub sendEmail {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Info("Creating notification email\n");
|
||||
Info('Creating notification email');
|
||||
|
||||
my $subject = substituteTags($Config{ZM_EMAIL_SUBJECT}, $filter, $Event);
|
||||
return 0 if !$subject;
|
||||
|
@ -753,7 +750,7 @@ sub sendEmail {
|
|||
my $body = substituteTags($Config{ZM_EMAIL_BODY}, $filter, $Event, \@attachments);
|
||||
return 0 if !$body;
|
||||
|
||||
Info("Sending notification email '$subject'\n");
|
||||
Info("Sending notification email '$subject'");
|
||||
|
||||
eval {
|
||||
if ( $Config{ZM_NEW_MAIL_MODULES} ) {
|
||||
|
@ -771,7 +768,7 @@ sub sendEmail {
|
|||
);
|
||||
### Add the attachments
|
||||
foreach my $attachment ( @attachments ) {
|
||||
Info( "Attaching '$attachment->{path}\n" );
|
||||
Info( "Attaching '$attachment->{path}'" );
|
||||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
|
@ -783,20 +780,20 @@ sub sendEmail {
|
|||
my $ssmtp_location = $Config{ZM_SSMTP_PATH};
|
||||
if ( !$ssmtp_location ) {
|
||||
if ( logDebugging() ) {
|
||||
Debug( "which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message\n" );
|
||||
Debug("which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message");
|
||||
}
|
||||
$ssmtp_location = qx('which ssmtp');
|
||||
}
|
||||
if ( !$ssmtp_location ) {
|
||||
Debug( "Unable tofind ssmtp, trying MIME::Lite->send" );
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
Debug('Unable tofind ssmtp, trying MIME::Lite->send');
|
||||
MIME::Lite->send('smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60);
|
||||
$mail->send();
|
||||
} else {
|
||||
### Send using SSMTP
|
||||
$mail->send( 'sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS} );
|
||||
$mail->send('sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS});
|
||||
}
|
||||
} else {
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
MIME::Lite->send('smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60);
|
||||
$mail->send();
|
||||
}
|
||||
} else {
|
||||
|
@ -809,29 +806,29 @@ sub sendEmail {
|
|||
);
|
||||
|
||||
foreach my $attachment ( @attachments ) {
|
||||
Info( "Attaching '$attachment->{path}\n" );
|
||||
Info("Attaching '$attachment->{path}'");
|
||||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Encoding => 'base64'
|
||||
);
|
||||
}
|
||||
$mail->smtpsend( Host => $Config{ZM_EMAIL_HOST}, MailFrom => $Config{ZM_FROM_EMAIL} );
|
||||
$mail->smtpsend(Host => $Config{ZM_EMAIL_HOST}, MailFrom => $Config{ZM_FROM_EMAIL});
|
||||
}
|
||||
};
|
||||
if ( $@ ) {
|
||||
Error( "Unable tosend email: $@" );
|
||||
return( 0 );
|
||||
Error("Unable tosend email: $@");
|
||||
return 0;
|
||||
} else {
|
||||
Info( "Notification email sent\n" );
|
||||
Info('Notification email sent');
|
||||
}
|
||||
my $sql = 'update Events set Emailed = 1 where Id = ?';
|
||||
my $sql = 'UPDATE Events SET Emailed = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal("Unable toprepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute($Event->{Id})
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
or Fatal("Unable toexecute '$sql': ".$dbh->errstr());
|
||||
|
||||
return( 1 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub sendMessage {
|
||||
|
@ -839,28 +836,28 @@ sub sendMessage {
|
|||
my $event = shift;
|
||||
|
||||
if ( ! $Config{ZM_FROM_EMAIL} ) {
|
||||
Error( "No 'from' email address defined, not sending message" );
|
||||
return( 0 );
|
||||
Error('No from email address defined, not sending message');
|
||||
return 0;
|
||||
}
|
||||
if ( ! $Config{ZM_MESSAGE_ADDRESS} ) {
|
||||
Error( 'No message address defined, not sending message' );
|
||||
return( 0 );
|
||||
Error('No message address defined, not sending message');
|
||||
return 0;
|
||||
}
|
||||
|
||||
Info( "Creating notification message\n" );
|
||||
Info('Creating notification message');
|
||||
|
||||
my $subject = substituteTags( $Config{ZM_MESSAGE_SUBJECT}, $filter, $event );
|
||||
return( 0 ) if ( !$subject );
|
||||
my $subject = substituteTags($Config{ZM_MESSAGE_SUBJECT}, $filter, $event);
|
||||
return 0 if !$subject;
|
||||
my @attachments;
|
||||
my $body = substituteTags( $Config{ZM_MESSAGE_BODY}, $filter, $event, \@attachments );
|
||||
return( 0 ) if ( !$body );
|
||||
my $body = substituteTags($Config{ZM_MESSAGE_BODY}, $filter, $event, \@attachments);
|
||||
return 0 if !$body;
|
||||
|
||||
Info( "Sending notification message '$subject'\n" );
|
||||
Info("Sending notification message '$subject'");
|
||||
|
||||
eval {
|
||||
if ( $Config{ZM_NEW_MAIL_MODULES} ) {
|
||||
### Create the multipart container
|
||||
my $mail = MIME::Lite->new (
|
||||
my $mail = MIME::Lite->new(
|
||||
From => $Config{ZM_FROM_EMAIL},
|
||||
To => $Config{ZM_MESSAGE_ADDRESS},
|
||||
Subject => $subject,
|
||||
|
@ -873,7 +870,7 @@ sub sendMessage {
|
|||
);
|
||||
### Add the attachments
|
||||
foreach my $attachment ( @attachments ) {
|
||||
Info( "Attaching '$attachment->{path}\n" );
|
||||
Info("Attaching '$attachment->{path}");
|
||||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
|
@ -885,20 +882,20 @@ sub sendMessage {
|
|||
my $ssmtp_location = $Config{ZM_SSMTP_PATH};
|
||||
if ( !$ssmtp_location ) {
|
||||
if ( logDebugging() ) {
|
||||
Debug( "which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message\n" );
|
||||
Debug("which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message");
|
||||
}
|
||||
$ssmtp_location = qx('which ssmtp');
|
||||
}
|
||||
if ( !$ssmtp_location ) {
|
||||
Debug( 'Unable tofind ssmtp, trying MIME::Lite->send' );
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
Debug('Unable tofind ssmtp, trying MIME::Lite->send');
|
||||
MIME::Lite->send(smtp=>$Config{ZM_EMAIL_HOST}, Timeout=>60);
|
||||
$mail->send();
|
||||
} else {
|
||||
### Send using SSMTP
|
||||
$mail->send( 'sendmail', $ssmtp_location, $Config{ZM_MESSAGE_ADDRESS} );
|
||||
$mail->send('sendmail', $ssmtp_location, $Config{ZM_MESSAGE_ADDRESS});
|
||||
}
|
||||
} else {
|
||||
MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 );
|
||||
MIME::Lite->send(smtp=>$Config{ZM_EMAIL_HOST}, Timeout=>60);
|
||||
$mail->send();
|
||||
}
|
||||
} else {
|
||||
|
@ -911,59 +908,60 @@ sub sendMessage {
|
|||
);
|
||||
|
||||
foreach my $attachment ( @attachments ) {
|
||||
Info( "Attaching '$attachment->{path}\n" );
|
||||
Info("Attaching '$attachment->{path}'");
|
||||
$mail->attach(
|
||||
Path => $attachment->{path},
|
||||
Type => $attachment->{type},
|
||||
Encoding => 'base64'
|
||||
);
|
||||
}
|
||||
$mail->smtpsend( Host => $Config{ZM_EMAIL_HOST},
|
||||
$mail->smtpsend(
|
||||
Host => $Config{ZM_EMAIL_HOST},
|
||||
MailFrom => $Config{ZM_FROM_EMAIL}
|
||||
);
|
||||
}
|
||||
};
|
||||
if ( $@ ) {
|
||||
Error( "Unable tosend email: $@" );
|
||||
return( 0 );
|
||||
Error("Unable tosend email: $@");
|
||||
return 0;
|
||||
} else {
|
||||
Info( "Notification message sent\n" );
|
||||
Info('Notification message sent');
|
||||
}
|
||||
my $sql = 'update Events set Messaged = 1 where Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
my $sql = 'UPDATE Events SET Messaged = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
or Fatal("Unable toprepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute($event->{Id})
|
||||
or Fatal("Unable toexecute '$sql': ".$dbh->errstr());
|
||||
|
||||
return( 1 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub executeCommand {
|
||||
my $filter = shift;
|
||||
my $event = shift;
|
||||
|
||||
my $event_path = getEventPath( $event );
|
||||
my $event_path = getEventPath($event);
|
||||
|
||||
my $command = $filter->{AutoExecuteCmd};
|
||||
$command .= " $event_path";
|
||||
$command = substituteTags( $command, $filter, $event );
|
||||
$command = substituteTags($command, $filter, $event);
|
||||
|
||||
Info( "Executing '$command'\n" );
|
||||
Info("Executing '$command'");
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
chomp( $output );
|
||||
Debug( "Output: $output\n" );
|
||||
chomp($output);
|
||||
Debug("Output: $output");
|
||||
}
|
||||
if ( $status ) {
|
||||
Error( "Command '$command' exited with status: $status\n" );
|
||||
return( 0 );
|
||||
Error("Command '$command' exited with status: $status");
|
||||
return 0;
|
||||
} else {
|
||||
my $sql = 'update Events set Executed = 1 where Id = ?';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
my $sql = 'UPDATE Events SET Executed = 1 WHERE Id = ?';
|
||||
my $sth = $dbh->prepare_cached($sql)
|
||||
or Fatal("Unable to prepare '$sql': ".$dbh->errstr());
|
||||
my $res = $sth->execute( $event->{Id} )
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
or Fatal("Unable to execute '$sql': ".$dbh->errstr());
|
||||
}
|
||||
return( 1 );
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ if ( $command =~ /^(?:start|restart)$/ ) {
|
|||
my $res = $sth->execute( @values )
|
||||
or Fatal( "Can't execute: ".$sth->errstr() );
|
||||
while( my $monitor = $sth->fetchrow_hashref() ) {
|
||||
if ( $monitor->{Function} ne 'None' ) {
|
||||
if ( $monitor->{Function} ne 'None' && $monitor->{Type} ne 'WebSite' ) {
|
||||
if ( $monitor->{Type} eq 'Local' ) {
|
||||
runCommand( "zmdc.pl start zmc -d $monitor->{Device}" );
|
||||
} else {
|
||||
|
|
|
@ -84,6 +84,7 @@ while( 1 ) {
|
|||
while( my $monitor = $sth->fetchrow_hashref() ) {
|
||||
my $now = time();
|
||||
next if $monitor->{Function} eq 'None';
|
||||
next if $monitor->{Type} eq 'WebSite';
|
||||
my $restart = 0;
|
||||
if ( zmMemVerify( $monitor ) ) {
|
||||
# Check we have got an image recently
|
||||
|
|
|
@ -69,7 +69,9 @@ Event::Event(
|
|||
untimedEvent = true;
|
||||
start_time = now;
|
||||
} else if ( start_time.tv_sec > now.tv_sec ) {
|
||||
Error("StartTime in the future");
|
||||
Error("StartTime in the future %d.%d > $d.%d",
|
||||
start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec
|
||||
);
|
||||
start_time = now;
|
||||
}
|
||||
|
||||
|
@ -257,7 +259,7 @@ Event::~Event() {
|
|||
"UPDATE Events SET Name='%s %" PRIu64 "', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' WHERE Id = %" PRIu64,
|
||||
monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id );
|
||||
db_mutex.lock();
|
||||
while ( mysql_query(&dbconn, sql) ) {
|
||||
while ( mysql_query(&dbconn, sql) && !zm_terminate ) {
|
||||
Error("Can't update event: %s reason: %s", sql, mysql_error(&dbconn));
|
||||
db_mutex.unlock();
|
||||
sleep(1);
|
||||
|
@ -422,16 +424,16 @@ void Event::updateNotes( const StringSetMap &newNoteSetMap ) {
|
|||
#else
|
||||
static char escapedNotes[ZM_SQL_MED_BUFSIZ];
|
||||
|
||||
mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() );
|
||||
mysql_real_escape_string(&dbconn, escapedNotes, notes.c_str(), notes.length());
|
||||
|
||||
snprintf( sql, sizeof(sql), "UPDATE Events SET Notes = '%s' WHERE Id = %" PRIu64, escapedNotes, id );
|
||||
snprintf(sql, sizeof(sql), "UPDATE Events SET Notes = '%s' WHERE Id = %" PRIu64, escapedNotes, id);
|
||||
db_mutex.lock();
|
||||
if ( mysql_query( &dbconn, sql ) ) {
|
||||
Error( "Can't insert event: %s", mysql_error( &dbconn ) );
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't insert event: %s", mysql_error(&dbconn));
|
||||
}
|
||||
db_mutex.unlock();
|
||||
#endif
|
||||
}
|
||||
} // end if update
|
||||
}
|
||||
|
||||
void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps ) {
|
||||
|
@ -485,7 +487,7 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
|
|||
snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %" PRIu64 ", %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec );
|
||||
|
||||
frameCount++;
|
||||
}
|
||||
} // end foreach frame
|
||||
|
||||
if ( frameCount ) {
|
||||
Debug( 1, "Adding %d/%d frames to DB", frameCount, n_frames );
|
||||
|
@ -543,7 +545,10 @@ Debug(3, "Writing video");
|
|||
|
||||
Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, Event::frame_type_names[frame_type] );
|
||||
static char sql[ZM_SQL_MED_BUFSIZ];
|
||||
snprintf(sql, sizeof(sql), "INSERT INTO Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %" PRIu64 ", %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", id, frames, frame_type_names[frame_type], timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score);
|
||||
snprintf(sql, sizeof(sql),
|
||||
"INSERT INTO Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score )"
|
||||
" VALUES ( %" PRIu64 ", %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )",
|
||||
id, frames, frame_type_names[frame_type], timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score);
|
||||
db_mutex.lock();
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't insert frame: %s", mysql_error(&dbconn));
|
||||
|
@ -556,7 +561,7 @@ Debug(3, "Writing video");
|
|||
|
||||
// We are writing a Bulk frame
|
||||
if ( frame_type == BULK ) {
|
||||
snprintf( sql, sizeof(sql),
|
||||
snprintf(sql, sizeof(sql),
|
||||
"UPDATE Events SET Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %" PRIu64,
|
||||
( delta_time.positive?"":"-" ),
|
||||
delta_time.sec, delta_time.fsec,
|
||||
|
@ -568,7 +573,7 @@ Debug(3, "Writing video");
|
|||
id
|
||||
);
|
||||
db_mutex.lock();
|
||||
while ( mysql_query(&dbconn, sql) ) {
|
||||
while ( mysql_query(&dbconn, sql) && !zm_terminate ) {
|
||||
Error("Can't update event: %s", mysql_error(&dbconn));
|
||||
db_mutex.unlock();
|
||||
sleep(1);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <getopt.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <glob.h>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <cinttypes>
|
||||
|
||||
#include "zm_ffmpeg.h"
|
||||
#include "zm_image.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
//
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_signal.h"
|
||||
|
||||
#if HAVE_LIBAVFORMAT
|
||||
|
||||
|
@ -180,7 +181,7 @@ int FfmpegCamera::Capture( Image &image ) {
|
|||
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread.
|
||||
|
||||
int frameComplete = false;
|
||||
while ( !frameComplete ) {
|
||||
while ( !frameComplete && !zm_terminate) {
|
||||
int avResult = av_read_frame(mFormatContext, &packet);
|
||||
char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
||||
if ( avResult < 0 ) {
|
||||
|
@ -295,12 +296,12 @@ int FfmpegCamera::Capture( Image &image ) {
|
|||
bytes += packet.size;
|
||||
zm_av_packet_unref( &packet );
|
||||
} // end while ! frameComplete
|
||||
return 1;
|
||||
return frameComplete ? 1 : 0;
|
||||
} // FfmpegCamera::Capture
|
||||
|
||||
int FfmpegCamera::PostCapture() {
|
||||
// Nothing to do here
|
||||
return( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FfmpegCamera::OpenFfmpeg() {
|
||||
|
|
|
@ -543,7 +543,7 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
|
|||
mysql_real_escape_string( &dbconn, escapedString, syslogStart, strlen(syslogStart) );
|
||||
|
||||
snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line );
|
||||
if (mysql_query(&dbconn, sql)) {
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Level tempDatabaseLevel = mDatabaseLevel;
|
||||
databaseLevel(NOLOG);
|
||||
Error("Can't insert log entry: sql(%s) error(%s)", sql, mysql_error(&dbconn));
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <glob.h>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
|
@ -1245,9 +1246,9 @@ bool Monitor::Analyse() {
|
|||
Info("%s: %d - Analysing at %.2f fps", name, image_count, new_fps);
|
||||
if ( fps != new_fps ) {
|
||||
fps = new_fps;
|
||||
db_mutex.lock();
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf(sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, fps, fps);
|
||||
db_mutex.lock();
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <cinttypes>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
|
|
|
@ -87,6 +87,7 @@ Options for use with monitors:
|
|||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "zm.h"
|
||||
#include "zm_db.h"
|
||||
|
|
|
@ -55,6 +55,22 @@ DocumentRoot /usr/share/zoneminder/www
|
|||
qq`
|
||||
ErrorLog $$opts{error_log}
|
||||
|
||||
Alias /zm/cache "/var/cache/zoneminder/cache"
|
||||
Alias /cache "/var/cache/zoneminder/cache"
|
||||
<Directory "/var/cache/zoneminder/cache">
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride None
|
||||
<IfModule mod_authz_core.c>
|
||||
# Apache 2.4
|
||||
Require all granted
|
||||
</IfModule>
|
||||
<IfModule !mod_authz_core.c>
|
||||
# Apache 2.2
|
||||
Order deny,allow
|
||||
Allow from all
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
ScriptAlias /zm/cgi-bin/ /usr/lib/zoneminder/cgi-bin/
|
||||
ScriptAlias /cgi-bin/ /usr/lib/zoneminder/cgi-bin/
|
||||
<Directory "/usr/lib/zoneminder/cgi-bin">
|
||||
|
@ -67,7 +83,6 @@ ScriptAlias /cgi-bin/ /usr/lib/zoneminder/cgi-bin/
|
|||
</Directory>
|
||||
|
||||
Alias /zm /usr/share/zoneminder/www
|
||||
|
||||
<Directory /usr/share/zoneminder/www>
|
||||
php_flag register_globals off
|
||||
Options +Indexes +FollowSymLinks
|
||||
|
@ -81,6 +96,32 @@ Alias /zm /usr/share/zoneminder/www
|
|||
Allow from all
|
||||
|
||||
</Directory>
|
||||
|
||||
# For better visibility, the following directives have been migrated from the
|
||||
# default .htaccess files included with the CakePHP project.
|
||||
# Parameters not set here are inherited from the parent directive above.
|
||||
<Directory "/usr/share/zoneminder/www/api">
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ app/webroot/ [L]
|
||||
RewriteRule (.*) app/webroot/$1 [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
||||
|
||||
<Directory "/usr/share/zoneminder/www/api/app">
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
||||
|
||||
<Directory "/usr/share/zoneminder/www/api/app/webroot">
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
||||
|
||||
`;
|
||||
if ( $$opts{protocol} eq 'https' ) {
|
||||
$template .= qq`
|
||||
|
|
|
@ -105,10 +105,11 @@ commonprep () {
|
|||
fi
|
||||
|
||||
# fix 32bit rpm builds
|
||||
patch --dry-run --silent -f -p1 < utils/packpack/setarch.patch
|
||||
if [ $? -eq 0 ]; then
|
||||
patch -p1 < utils/packpack/setarch.patch
|
||||
fi
|
||||
# FIXME: breaks arm rpm builds
|
||||
#patch --dry-run --silent -f -p1 < utils/packpack/setarch.patch
|
||||
#if [ $? -eq 0 ]; then
|
||||
# patch -p1 < utils/packpack/setarch.patch
|
||||
#fi
|
||||
|
||||
# The rpm specfile requires we download each submodule as a tarball then manually move it into place
|
||||
# Might as well do this for Debian as well, rather than git submodule init
|
||||
|
|
|
@ -6,14 +6,14 @@ class HostController extends AppController {
|
|||
public $components = array('RequestHandler');
|
||||
|
||||
public function daemonCheck($daemon=false, $args=false) {
|
||||
$string = Configure::read('ZM_PATH_BIN')."/zmdc.pl check";
|
||||
$string = Configure::read('ZM_PATH_BIN').'/zmdc.pl check';
|
||||
if ( $daemon ) {
|
||||
$string .= " $daemon";
|
||||
if ( $args )
|
||||
$string .= " $args";
|
||||
}
|
||||
$result = exec( $string );
|
||||
$result = preg_match( '/running/', $result );
|
||||
$result = exec($string);
|
||||
$result = preg_match('/running/', $result);
|
||||
|
||||
$this->set(array(
|
||||
'result' => $result,
|
||||
|
@ -31,10 +31,18 @@ class HostController extends AppController {
|
|||
}
|
||||
|
||||
function getAuthHash() {
|
||||
if ( $zmOptAuth == '1' ) {
|
||||
require_once '../../../includes/auth.php';
|
||||
$this->set(array(
|
||||
'auth_hash'=> generateAuthHash( ZM_AUTH_HASH_IPS ),
|
||||
'auth_hash' => generateAuthHash(ZM_AUTH_HASH_IPS),
|
||||
'_serialize' => array('auth_hash')
|
||||
) );
|
||||
} else {
|
||||
$this->set(array(
|
||||
'auth_hash' => '',
|
||||
'_serialize' => array('auth_hash')
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
// If $mid is set, only return disk usage for that monitor
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1351dde6b4c75b215099ae8bcf5a21d6c6e10298
|
||||
Subproject commit 0bd63fb464957080ead342db58ca9e01532cf1ef
|
|
@ -451,6 +451,11 @@ class Event {
|
|||
$values[] = $this->{'Id'};
|
||||
dbQuery( $sql, $values );
|
||||
}
|
||||
public function link_to($text=null) {
|
||||
if ( !$text )
|
||||
$text = $this->{'Id'};
|
||||
return '<a href="?view=event&eid='. $this->{'Id'}.'">'.$text.'</a>';
|
||||
}
|
||||
|
||||
} # end class
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ class Storage {
|
|||
if ( ! $row ) {
|
||||
Error("Unable to load Storage record for Id=" . $IdOrRow );
|
||||
}
|
||||
} elseif ( is_array( $IdOrRow ) ) {
|
||||
} else if ( is_array($IdOrRow) ) {
|
||||
$row = $IdOrRow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -299,10 +299,12 @@ if ( isset($_REQUEST['object']) and $_REQUEST['object'] == 'Monitor' ) {
|
|||
continue;
|
||||
}
|
||||
$Monitor = new Monitor( $mid );
|
||||
if ( $Monitor->Type() != 'WebSite' ) {
|
||||
$Monitor->zmaControl('stop');
|
||||
$Monitor->zmcControl('stop');
|
||||
}
|
||||
$Monitor->save( $_REQUEST['newMonitor'] );
|
||||
if ($Monitor->Function() != 'None' ) {
|
||||
if ($Monitor->Function() != 'None' && $Monitor->Type() != 'WebSite' ) {
|
||||
$Monitor->zmcControl('start');
|
||||
if ( $Monitor->Enabled() ) {
|
||||
$Monitor->zmaControl('start');
|
||||
|
@ -330,7 +332,7 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
|
|||
|
||||
$monitor['Function'] = $newFunction;
|
||||
$monitor['Enabled'] = $newEnabled;
|
||||
if ( daemonCheck() ) {
|
||||
if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) {
|
||||
$restart = ($oldFunction == 'None') || ($newFunction == 'None') || ($newEnabled != $oldEnabled);
|
||||
zmaControl( $monitor, 'stop' );
|
||||
zmcControl( $monitor, $restart?'restart':'' );
|
||||
|
@ -371,7 +373,7 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
|
|||
} else {
|
||||
dbQuery( 'INSERT INTO Zones SET MonitorId=?, '.implode( ', ', $changes ), array( $mid ) );
|
||||
}
|
||||
if ( daemonCheck() ) {
|
||||
if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) {
|
||||
if ( $_REQUEST['newZone']['Type'] == 'Privacy' ) {
|
||||
zmaControl( $monitor, 'stop' );
|
||||
zmcControl( $monitor, 'restart' );
|
||||
|
@ -399,7 +401,7 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
|
|||
}
|
||||
}
|
||||
if($changes>0) {
|
||||
if ( daemonCheck() ) {
|
||||
if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) {
|
||||
zmaControl( $mid, 'restart' );
|
||||
}
|
||||
$refreshParent = true;
|
||||
|
@ -424,7 +426,7 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) {
|
|||
$deletedZid = 1;
|
||||
}
|
||||
if ( $deletedZid ) {
|
||||
if ( daemonCheck() ) {
|
||||
if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) {
|
||||
if ( $zone['Type'] == 'Privacy' ) {
|
||||
zmaControl( $mid, 'stop' );
|
||||
zmcControl( $mid, 'restart' );
|
||||
|
@ -492,8 +494,10 @@ if ( canEdit( 'Monitors' ) ) {
|
|||
if ( $mid ) {
|
||||
|
||||
# If we change anything that changes the shared mem size, zma can complain. So let's stop first.
|
||||
if ( $monitor['Type'] != 'WebSite' ) {
|
||||
zmaControl( $monitor, 'stop' );
|
||||
zmcControl( $monitor, 'stop' );
|
||||
}
|
||||
dbQuery( 'UPDATE Monitors SET '.implode( ', ', $changes ).' WHERE Id=?', array($mid) );
|
||||
// Groups will be added below
|
||||
if ( isset($changes['Name']) or isset($changes['StorageId']) ) {
|
||||
|
@ -606,8 +610,10 @@ if ( canEdit( 'Monitors' ) ) {
|
|||
$new_monitor = new Monitor($mid);
|
||||
//fixDevices();
|
||||
|
||||
if ( $monitor['Type'] != 'WebSite' ) {
|
||||
$new_monitor->zmcControl('start');
|
||||
$new_monitor->zmaControl('start');
|
||||
}
|
||||
|
||||
if ( $new_monitor->Controllable() ) {
|
||||
require_once( 'control_functions.php' );
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
function userLogin( $username, $password='', $passwordHashed=false ) {
|
||||
function userLogin($username, $password='', $passwordHashed=false) {
|
||||
global $user, $cookies;
|
||||
|
||||
$sql = 'SELECT * FROM Users WHERE Enabled=1';
|
||||
|
@ -29,10 +29,10 @@ function userLogin( $username, $password='', $passwordHashed=false ) {
|
|||
} else {
|
||||
$sql .= ' AND Username=? AND Password=password(?)';
|
||||
}
|
||||
$sql_values = array( $username, $password );
|
||||
$sql_values = array($username, $password);
|
||||
} else {
|
||||
$sql .= ' AND Username=?';
|
||||
$sql_values = array( $username );
|
||||
$sql_values = array($username);
|
||||
}
|
||||
session_start();
|
||||
$_SESSION['username'] = $username;
|
||||
|
@ -41,8 +41,8 @@ function userLogin( $username, $password='', $passwordHashed=false ) {
|
|||
$_SESSION['password'] = $password;
|
||||
}
|
||||
$_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking
|
||||
if ( $dbUser = dbFetchOne( $sql, NULL, $sql_values ) ) {
|
||||
Info( "Login successful for user \"$username\"" );
|
||||
if ( $dbUser = dbFetchOne($sql, NULL, $sql_values) ) {
|
||||
Info("Login successful for user \"$username\"");
|
||||
$_SESSION['user'] = $user = $dbUser;
|
||||
unset($_SESSION['loginFailed']);
|
||||
if ( ZM_AUTH_TYPE == 'builtin' ) {
|
||||
|
@ -50,30 +50,30 @@ function userLogin( $username, $password='', $passwordHashed=false ) {
|
|||
}
|
||||
session_regenerate_id();
|
||||
} else {
|
||||
Warning( "Login denied for user \"$username\"" );
|
||||
Warning("Login denied for user \"$username\"");
|
||||
$_SESSION['loginFailed'] = true;
|
||||
unset( $user );
|
||||
unset($user);
|
||||
}
|
||||
session_write_close();
|
||||
}
|
||||
} # end function userLogin
|
||||
|
||||
function userLogout() {
|
||||
global $user;
|
||||
Info( 'User "'.$user['Username'].'" logged out' );
|
||||
Info('User "'.$user['Username'].'" logged out');
|
||||
session_start();
|
||||
unset( $_SESSION['user'] );
|
||||
unset( $user );
|
||||
unset($_SESSION['user']);
|
||||
unset($user);
|
||||
|
||||
session_destroy();
|
||||
}
|
||||
|
||||
function getAuthUser( $auth ) {
|
||||
function getAuthUser($auth) {
|
||||
if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' && !empty($auth) ) {
|
||||
$remoteAddr = '';
|
||||
if ( ZM_AUTH_HASH_IPS ) {
|
||||
$remoteAddr = $_SERVER['REMOTE_ADDR'];
|
||||
if ( !$remoteAddr ) {
|
||||
Error( "Can't determine remote address for authentication, using empty string" );
|
||||
Error("Can't determine remote address for authentication, using empty string");
|
||||
$remoteAddr = '';
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ function getAuthUser( $auth ) {
|
|||
return false;
|
||||
} // end getAuthUser($auth)
|
||||
|
||||
function generateAuthHash( $useRemoteAddr ) {
|
||||
function generateAuthHash($useRemoteAddr) {
|
||||
if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) {
|
||||
# regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800
|
||||
$time = time();
|
||||
|
@ -119,7 +119,7 @@ function generateAuthHash( $useRemoteAddr ) {
|
|||
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
|
||||
}
|
||||
#Logger::Debug("Generated using hour:".$local_time[2] . ' mday:' . $local_time[3] . ' month:'.$local_time[4] . ' year: ' . $local_time[5] );
|
||||
$auth = md5( $authKey );
|
||||
$auth = md5($authKey);
|
||||
session_start();
|
||||
$_SESSION['AuthHash'] = $auth;
|
||||
$_SESSION['AuthHashGeneratedAt'] = $time;
|
||||
|
@ -135,22 +135,22 @@ function generateAuthHash( $useRemoteAddr ) {
|
|||
return $auth;
|
||||
}
|
||||
|
||||
function visibleMonitor( $mid ) {
|
||||
function visibleMonitor($mid) {
|
||||
global $user;
|
||||
|
||||
return( empty($user['MonitorIds']) || in_array( $mid, explode( ',', $user['MonitorIds'] ) ) );
|
||||
return ( empty($user['MonitorIds']) || in_array($mid, explode(',', $user['MonitorIds'])) );
|
||||
}
|
||||
|
||||
function canView( $area, $mid=false ) {
|
||||
function canView($area, $mid=false) {
|
||||
global $user;
|
||||
|
||||
return( ($user[$area] == 'View' || $user[$area] == 'Edit') && ( !$mid || visibleMonitor( $mid ) ) );
|
||||
return ( ($user[$area] == 'View' || $user[$area] == 'Edit') && ( !$mid || visibleMonitor($mid) ) );
|
||||
}
|
||||
|
||||
function canEdit( $area, $mid=false ) {
|
||||
function canEdit($area, $mid=false) {
|
||||
global $user;
|
||||
|
||||
return( $user[$area] == 'Edit' && ( !$mid || visibleMonitor( $mid ) ) );
|
||||
return ( $user[$area] == 'Edit' && ( !$mid || visibleMonitor($mid) ));
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -133,7 +133,7 @@ function dbQuery( $sql, $params=NULL ) {
|
|||
}
|
||||
} else {
|
||||
if ( defined('ZM_DB_DEBUG') ) {
|
||||
Logger::Debug("SQL: $sql values:" . $params?implode(',',$params):'' );
|
||||
Logger::Debug("SQL: $sql values:" . ($params?implode(',',$params):'') );
|
||||
}
|
||||
$result = $dbConn->query($sql);
|
||||
}
|
||||
|
|
|
@ -280,6 +280,27 @@ function getImageStill( $id, $src, $width, $height, $title='' ) {
|
|||
return '<img id="'.$id.'" src="'.$src.'" alt="'.$title.'"'.(validInt($width)?' width="'.$width.'"':'').(validInt($height)?' height="'.$height.'"':'').'/>';
|
||||
}
|
||||
|
||||
function getWebSiteUrl( $id, $src, $width, $height, $title='' ) {
|
||||
# Prevent unsightly warnings when php cannot verify the ssl certificate
|
||||
stream_context_set_default( [
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
],
|
||||
]);
|
||||
# The End User can turn off the following warning under Options -> Web
|
||||
if ( ZM_WEB_XFRAME_WARN ) {
|
||||
$header = get_headers($src, 1);
|
||||
# If the target website has set X-Frame-Options, check it for "sameorigin" and warn the end user
|
||||
if (array_key_exists('X-Frame-Options', $header)) {
|
||||
$header = $header['X-Frame-Options'];
|
||||
if ( stripos($header, 'sameorigin') === 0 )
|
||||
Warning("Web site $src has X-Frame-Options set to sameorigin. An X-Frame-Options browser plugin is required to display this site.");
|
||||
}
|
||||
}
|
||||
return '<object id="'.$id.'" data="'.$src.'" alt="'.$title.'" width="'.$width.'" height="'.$height.'"></object>';
|
||||
}
|
||||
|
||||
function outputControlStill( $src, $width, $height, $monitor, $scale, $target ) {
|
||||
?>
|
||||
<form name="ctrlForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>" target="<?php echo $target ?>">
|
||||
|
@ -495,11 +516,11 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) {
|
|||
switch( $types[$key] ) {
|
||||
case 'set' :
|
||||
{
|
||||
if ( is_array( $newValues[$key] ) ) {
|
||||
if ( join(',',$newValues[$key]) != $values[$key] ) {
|
||||
if ( is_array($newValues[$key]) ) {
|
||||
if ( (!isset($values[$key])) or ( join(',',$newValues[$key]) != $values[$key] ) ) {
|
||||
$changes[$key] = "`$key` = ".dbEscape(join(',',$newValues[$key]));
|
||||
}
|
||||
} elseif ( $values[$key] ) {
|
||||
} else if ( (!isset($values[$key])) or $values[$key] ) {
|
||||
$changes[$key] = "`$key` = ''";
|
||||
}
|
||||
break;
|
||||
|
@ -548,7 +569,7 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) {
|
|||
}
|
||||
case 'raw' :
|
||||
{
|
||||
if ( $values[$key] != $value ) {
|
||||
if ( (!isset($values[$key])) or ($values[$key] != $value) ) {
|
||||
$changes[$key] = $key . ' = '.dbEscape($value);
|
||||
}
|
||||
break;
|
||||
|
@ -1004,8 +1025,15 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
|||
$filter['sql'] .= 'M.'.preg_replace('/^Monitor/', '', $terms[$i]['attr']);
|
||||
break;
|
||||
case 'ServerId':
|
||||
case 'MonitorServerId':
|
||||
$filter['sql'] .= 'M.ServerId';
|
||||
break;
|
||||
case 'StorageServerId':
|
||||
$filter['sql'] .= 'S.ServerId';
|
||||
break;
|
||||
case 'FilterServerId':
|
||||
$filter['sql'] .= ZM_SERVER_ID;
|
||||
break;
|
||||
# Unspecified start or end, so assume start, this is to support legacy filters
|
||||
case 'DateTime':
|
||||
$filter['sql'] .= 'E.StartTime';
|
||||
|
@ -1100,6 +1128,9 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&') {
|
|||
case 'Notes':
|
||||
$value = dbEscape($value);
|
||||
break;
|
||||
case 'MonitorServerId':
|
||||
case 'FilterServerId':
|
||||
case 'StorageServerId':
|
||||
case 'ServerId':
|
||||
if ( $value == 'ZM_SERVER_ID' ) {
|
||||
$value = ZM_SERVER_ID;
|
||||
|
@ -2128,8 +2159,14 @@ function getStreamHTML( $monitor, $options = array() ) {
|
|||
$options['buffer'] = $monitor->StreamReplayBuffer();
|
||||
//Warning("width: " . $options['width'] . ' height: ' . $options['height']. ' scale: ' . $options['scale'] );
|
||||
|
||||
if ( $monitor->Type() == "WebSite" ) {
|
||||
return getWebSiteUrl( 'liveStream'.$monitor->Id(), $monitor->Path(),
|
||||
( isset($options['width']) ? $options['width'] : NULL ),
|
||||
( isset($options['height']) ? $options['height'] : NULL ),
|
||||
$monitor->Name()
|
||||
);
|
||||
//FIXME, the width and height of the image need to be scaled.
|
||||
if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||
} else if ( ZM_WEB_STREAM_METHOD == 'mpeg' && ZM_MPEG_LIVE_FORMAT ) {
|
||||
$streamSrc = $monitor->getStreamSrc( array(
|
||||
'mode'=>'mpeg',
|
||||
'scale'=>(isset($options['scale'])?$options['scale']:100),
|
||||
|
|
|
@ -130,7 +130,9 @@ $SLANG = array(
|
|||
'AttrMonitorId' => 'Monitor Id',
|
||||
'AttrMonitorName' => 'Monitor Name',
|
||||
'AttrStorageArea' => 'Storage Area',
|
||||
'AttrServer' => 'Server',
|
||||
'AttrFilterServer' => 'Server Filter is Running On',
|
||||
'AttrMonitorServer' => 'Server Monitor is Running On',
|
||||
'AttrStorageServer' => 'Server Hosting Storage',
|
||||
'AttrStateId' => 'Run State',
|
||||
'AttrName' => 'Name',
|
||||
'AttrNotes' => 'Notes',
|
||||
|
@ -174,8 +176,10 @@ $SLANG = array(
|
|||
'BadSectionLength' => 'Section length must be an integer of 30 or more',
|
||||
'BadSignalCheckColour' => 'Signal check colour must be a valid RGB colour string',
|
||||
'BadStreamReplayBuffer' => 'Stream replay buffer must be an integer of zero or more',
|
||||
'BadSourceType' => 'Source Type \"Web Site\" requires the Function to be set to \"Monitor\"',
|
||||
'BadWarmupCount' => 'Warmup frames must be an integer of zero or more',
|
||||
'BadWebColour' => 'Web colour must be a valid web colour string',
|
||||
'BadWebSitePath' => 'Please enter a complete website url, including the http:// or https:// prefix.',
|
||||
'BadWidth' => 'Width must be set to a valid value',
|
||||
'Bandwidth' => 'Bandwidth',
|
||||
'BandwidthHead' => 'Bandwidth', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
|
||||
|
@ -768,6 +772,7 @@ $SLANG = array(
|
|||
'Watch' => 'Watch',
|
||||
'WebColour' => 'Web Colour',
|
||||
'Web' => 'Web',
|
||||
'WebSiteUrl' => 'Website URL',
|
||||
'Week' => 'Week',
|
||||
'WhiteBalance' => 'White Balance',
|
||||
'White' => 'White',
|
||||
|
|
|
@ -244,7 +244,7 @@ function getNavBarHTML($reload = null) {
|
|||
if ( logToDatabase() > Logger::NOLOG ) {
|
||||
if ( ! ZM_RUN_AUDIT ) {
|
||||
# zmaudit can clean the logs, but if we aren't running it, then we should clecan them regularly
|
||||
dbQuery('DELETE FROM Logs WHERE TimeKey < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.')');
|
||||
dbQuery('DELETE FROM Logs WHERE TimeKey < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100');
|
||||
}
|
||||
echo makePopupLink( '?view=log', 'zmLog', 'log', '<span class="'.logState().'">'.translate('Log').'</span>' );
|
||||
}
|
||||
|
|
|
@ -111,6 +111,9 @@ $status_counts = array();
|
|||
for ( $i = 0; $i < count($displayMonitors); $i++ ) {
|
||||
$monitor = &$displayMonitors[$i];
|
||||
if ( ! $monitor['Status'] ) {
|
||||
if ( $monitor['Type'] == 'WebSite' )
|
||||
$monitor['Status'] = 'Running';
|
||||
else
|
||||
$monitor['Status'] = 'NotRunning';
|
||||
}
|
||||
if ( !isset($status_counts[$monitor['Status']]) )
|
||||
|
@ -238,7 +241,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
?>
|
||||
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
|
||||
<?php
|
||||
if ( (!$monitor['Status']) or ($monitor['Status'] == 'NotRunning') ) {
|
||||
if ( (!$monitor['Status'] || $monitor['Status'] == 'NotRunning') && $monitor['Type']!='WebSite' ) {
|
||||
$source_class = 'errorText';
|
||||
} else {
|
||||
if ( $monitor['CaptureFPS'] == '0.00' ) {
|
||||
|
@ -256,7 +259,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
if ( !$monitor['Enabled'] )
|
||||
$fclass .= ' disabledText';
|
||||
$scale = max( reScale( SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
|
||||
$stream_available = canView('Stream') && $monitor['CaptureFPS'] && $monitor['Function'] != 'None';
|
||||
$stream_available = canView('Stream') and $monitor['Type']=='WebSite' or ($monitor['CaptureFPS'] && $monitor['Function'] != 'None');
|
||||
$dot_class=$source_class;
|
||||
if ( $fclass != 'infoText' ) $dot_class=$fclass;
|
||||
|
||||
|
@ -313,7 +316,7 @@ if ( $fclass != 'infoText' ) $dot_class=$fclass;
|
|||
}
|
||||
} elseif ( $monitor['Type'] == 'File' || $monitor['Type'] == 'cURL' ) {
|
||||
$source = preg_replace( '/^.*\//', '', $monitor['Path'] );
|
||||
} elseif ( $monitor['Type'] == 'Ffmpeg' || $monitor['Type'] == 'Libvlc' ) {
|
||||
} elseif ( $monitor['Type'] == 'Ffmpeg' || $monitor['Type'] == 'Libvlc' || $monitor['Type'] == 'WebSite' ) {
|
||||
$url_parts = parse_url( $monitor['Path'] );
|
||||
unset($url_parts['user']);
|
||||
unset($url_parts['pass']);
|
||||
|
|
|
@ -101,7 +101,10 @@ $attrTypes = array(
|
|||
'DiskSpace' => translate('AttrDiskSpace'),
|
||||
'SystemLoad' => translate('AttrSystemLoad'),
|
||||
'StorageId' => translate('AttrStorageArea'),
|
||||
'ServerId' => translate('AttrServer'),
|
||||
'ServerId' => translate('AttrMonitorServer'),
|
||||
'FilterServerId' => translate('AttrFilterServer'),
|
||||
'MonitorServerId' => translate('AttrMonitorServer'),
|
||||
'StorageServerId' => translate('AttrStorageServer'),
|
||||
'StateId' => translate('AttrStateId'),
|
||||
);
|
||||
|
||||
|
@ -268,7 +271,7 @@ for ( $i=0; $i < count($terms); $i++ ) {
|
|||
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
|
||||
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $monitors, $term['val'] ); ?></td>
|
||||
<?php
|
||||
} elseif ( $term['attr'] == 'ServerId' ) {
|
||||
} elseif ( $term['attr'] == 'ServerId' || $term['attr'] == 'MonitorServerId' || $term['attr'] == 'StorageServerId' || $term['attr'] == 'FilterServerId' ) {
|
||||
?>
|
||||
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
|
||||
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $servers, $term['val'] ); ?></td>
|
||||
|
|
|
@ -142,7 +142,9 @@ function parseRows (rows) {
|
|||
inputTds.eq(6).find(':input[value="-"]').prop('disabled', false);
|
||||
}
|
||||
|
||||
if (inputTds.eq(2).children().val() == "Archived") { //Archived types
|
||||
var attr = inputTds.eq(2).children().val();
|
||||
|
||||
if ( attr == "Archived") { //Archived types
|
||||
inputTds.eq(3).html('equal to<input type="hidden" name="filter[Query][terms][' + rowNum + '][op]" value="=">');
|
||||
let archiveSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (let i = 0; i < archiveTypes.length; i++) {
|
||||
|
@ -151,7 +153,7 @@ function parseRows (rows) {
|
|||
let archiveVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(archiveSelect).children().val(archiveVal).chosen({width: "101%"});
|
||||
|
||||
} else if (inputTds.eq(2).children().val().indexOf('Weekday') >= 0) { //Weekday selection
|
||||
} else if ( attr.indexOf('Weekday') >= 0 ) { //Weekday selection
|
||||
let weekdaySelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (let i = 0; i < weekdays.length; i++) {
|
||||
weekdaySelect.append('<option value="' + i + '">' + weekdays[i] + '</option>');
|
||||
|
@ -159,7 +161,7 @@ function parseRows (rows) {
|
|||
let weekdayVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(weekdaySelect).children().val(weekdayVal).chosen({width: "101%"});
|
||||
|
||||
} else if (inputTds.eq(2).children().val() == 'StateId') { //Run state
|
||||
} else if ( attr == 'StateId' ) { //Run state
|
||||
let stateSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (let key in states) {
|
||||
stateSelect.append('<option value="' + key + '">' + states[key] + '</option>');
|
||||
|
@ -167,8 +169,7 @@ function parseRows (rows) {
|
|||
let stateVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(stateSelect).children().val(stateVal).chosen({width: "101%"});
|
||||
|
||||
|
||||
} else if (inputTds.eq(2).children().val() == 'ServerId') { //Select Server
|
||||
} else if ( attr == 'ServerId' || attr == 'MonitorServerId' || attr == 'StorageServerId' || attr == 'FilterServerId' ) { //Select Server
|
||||
let serverSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (let key in servers) {
|
||||
serverSelect.append('<option value="' + key + '">' + servers[key] + '</option>');
|
||||
|
@ -176,21 +177,15 @@ function parseRows (rows) {
|
|||
let serverVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(serverSelect).children().val(serverVal).chosen({width: "101%"});
|
||||
|
||||
} else if (inputTds.eq(2).children().val() == 'StorageId') { //Choose by storagearea
|
||||
} else if ( attr == 'StorageId' ) { //Choose by storagearea
|
||||
let storageSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for ( key in storageareas ) {
|
||||
console.log(key + ' ' + storageareas[key]);
|
||||
storageSelect.append('<option value="' + key + '">' + storageareas[key] + '</option>');
|
||||
}
|
||||
/*
|
||||
for (let i=0; i < storageareas.length; i++) {
|
||||
storageSelect.append('<option value="' + i + '">' + storageareas[i] + '</option>');
|
||||
}
|
||||
*/
|
||||
let storageVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(storageSelect).children().val(storageVal).chosen({width: "101%"});
|
||||
|
||||
} else if (inputTds.eq(2).children().val() == 'MonitorName') { //Monitor names
|
||||
} else if ( attr == 'MonitorName' ) { //Monitor names
|
||||
let monitorSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
|
||||
for (let key in monitors) {
|
||||
monitorSelect.append('<option value="' + key + '">' + monitors[key] + '</option>');
|
||||
|
@ -208,15 +203,15 @@ console.log(key + ' ' + storageareas[key]);
|
|||
let textVal = inputTds.eq(4).children().val();
|
||||
inputTds.eq(4).html(textInput).children().val(textVal);
|
||||
}
|
||||
if (inputTds.eq(2).children().val().endsWith('DateTime')) { //Start/End DateTime
|
||||
if ( attr.endsWith('DateTime') ) { //Start/End DateTime
|
||||
inputTds.eq(4).children().datetimepicker({timeFormat: "HH:mm:ss", dateFormat: "yy-mm-dd", maxDate: 0, constrainInput: false});
|
||||
} else if (inputTds.eq(2).children().val().endsWith('Date')) { //Start/End Date
|
||||
} else if ( attr.endsWith('Date') ) { //Start/End Date
|
||||
inputTds.eq(4).children().datepicker({dateFormat: "yy-mm-dd", maxDate: 0, constrainInput: false});
|
||||
} else if (inputTds.eq(2).children().val().endsWith('Time')) { //Start/End Time
|
||||
} else if ( attr.endsWith('Time')) { //Start/End Time
|
||||
inputTds.eq(4).children().timepicker({timeFormat: "HH:mm:ss", constrainInput: false});
|
||||
}
|
||||
|
||||
let attr = inputTds.find("[name$='attr\\]']") // Set attr list id and name
|
||||
attr = inputTds.find("[name$='attr\\]']") // Set attr list id and name
|
||||
let term = attr.attr('name').split(/[[\]]{1,2}/);
|
||||
term.length--;
|
||||
term.shift();
|
||||
|
|
|
@ -54,14 +54,6 @@ function validateForm( form ) {
|
|||
else if ( monitorNames[form.elements['newMonitor[Name]'].value] )
|
||||
errors[errors.length] = "<?php echo translate('DuplicateMonitorName') ?>";
|
||||
|
||||
if ( form.elements['newMonitor[AnalysisFPSLimit]'].value && !(parseFloat(form.elements['newMonitor[AnalysisFPSLimit]'].value) > 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadAnalysisFPS') ?>";
|
||||
if ( form.elements['newMonitor[MaxFPS]'].value && !(parseFloat(form.elements['newMonitor[MaxFPS]'].value) > 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadMaxFPS') ?>";
|
||||
if ( form.elements['newMonitor[AlarmMaxFPS]'].value && !(parseFloat(form.elements['newMonitor[AlarmMaxFPS]'].value) > 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadAlarmMaxFPS') ?>";
|
||||
if ( !form.elements['newMonitor[RefBlendPerc]'].value || (parseInt(form.elements['newMonitor[RefBlendPerc]'].value) > 100 ) || (parseInt(form.elements['newMonitor[RefBlendPerc]'].value) < 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadRefBlendPerc') ?>";
|
||||
if ( form.elements['newMonitor[Type]'].value == 'Local' ) {
|
||||
if ( !form.elements['newMonitor[Palette]'].value || !form.elements['newMonitor[Palette]'].value.match( /^\d+$/ ) )
|
||||
errors[errors.length] = "<?php echo translate('BadPalette') ?>";
|
||||
|
@ -81,7 +73,24 @@ function validateForm( form ) {
|
|||
} else if ( form.elements['newMonitor[Type]'].value == 'File' ) {
|
||||
if ( !form.elements['newMonitor[Path]'].value )
|
||||
errors[errors.length] = "<?php echo translate('BadPath') ?>";
|
||||
} else if ( form.elements['newMonitor[Type]'].value == 'WebSite' ) {
|
||||
if ( form.elements['newMonitor[Function]'].value != 'Monitor' && form.elements['newMonitor[Function]'].value != 'None')
|
||||
errors[errors.length] = "<?php echo translate('BadSourceType') ?>";
|
||||
if ( form.elements['newMonitor[Path]'].value.search(/^https?:\/\//i) )
|
||||
errors[errors.length] = "<?php echo translate('BadWebSitePath') ?>";
|
||||
}
|
||||
|
||||
if ( form.elements['newMonitor[Type]'].value != 'WebSite' ) {
|
||||
|
||||
if ( form.elements['newMonitor[AnalysisFPSLimit]'].value && !(parseFloat(form.elements['newMonitor[AnalysisFPSLimit]'].value) > 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadAnalysisFPS') ?>";
|
||||
if ( form.elements['newMonitor[MaxFPS]'].value && !(parseFloat(form.elements['newMonitor[MaxFPS]'].value) > 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadMaxFPS') ?>";
|
||||
if ( form.elements['newMonitor[AlarmMaxFPS]'].value && !(parseFloat(form.elements['newMonitor[AlarmMaxFPS]'].value) > 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadAlarmMaxFPS') ?>";
|
||||
if ( !form.elements['newMonitor[RefBlendPerc]'].value || (parseInt(form.elements['newMonitor[RefBlendPerc]'].value) > 100 ) || (parseInt(form.elements['newMonitor[RefBlendPerc]'].value) < 0 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadRefBlendPerc') ?>";
|
||||
|
||||
if ( !form.elements['newMonitor[Colours]'].value || (parseInt(form.elements['newMonitor[Colours]'].value) != 1 && parseInt(form.elements['newMonitor[Colours]'].value) != 3 && parseInt(form.elements['newMonitor[Colours]'].value) != 4 ) )
|
||||
errors[errors.length] = "<?php echo translate('BadColours') ?>";
|
||||
if ( !form.elements['newMonitor[Width]'].value || !(parseInt(form.elements['newMonitor[Width]'].value) > 0 ) )
|
||||
|
@ -120,6 +129,8 @@ function validateForm( form ) {
|
|||
if ( !form.elements['newMonitor[WebColour]'].value || !form.elements['newMonitor[WebColour]'].value.match( /^[#0-9a-zA-Z]+$/ ) )
|
||||
errors[errors.length] = "<?php echo translate('BadWebColour') ?>";
|
||||
|
||||
}
|
||||
|
||||
if ( errors.length ) {
|
||||
alert( errors.join( "\n" ) );
|
||||
return( false );
|
||||
|
|
|
@ -12,6 +12,15 @@ function Monitor( monitorData ) {
|
|||
if ( auth_hash )
|
||||
this.streamCmdParms += '&auth='+auth_hash;
|
||||
this.streamCmdTimer = null;
|
||||
this.type = monitorData.type;
|
||||
this.refresh = monitorData.refresh;
|
||||
this.start = function( delay ) {
|
||||
if ( this.streamCmdQuery )
|
||||
this.streamCmdTimer = this.streamCmdQuery.delay( delay, this );
|
||||
else
|
||||
console.log("No streamCmdQuery");
|
||||
};
|
||||
|
||||
|
||||
this.setStateClass = function( element, stateClass ) {
|
||||
if ( !element.hasClass( stateClass ) ) {
|
||||
|
@ -68,7 +77,7 @@ function Monitor( monitorData ) {
|
|||
else
|
||||
stateClass = "idle";
|
||||
|
||||
if ( !COMPACT_MONTAGE ) {
|
||||
if ( (!COMPACT_MONTAGE) && (this.type != 'WebSite') ) {
|
||||
$('fpsValue'+this.id).set( 'text', this.status.fps );
|
||||
$('stateValue'+this.id).set( 'text', stateStrings[this.alarmState] );
|
||||
this.setStateClass( $('monitorState'+this.id), stateClass );
|
||||
|
@ -137,9 +146,12 @@ function Monitor( monitorData ) {
|
|||
this.streamCmdReq.cancel();
|
||||
}
|
||||
//console.log("Starting CmdQuery for " + this.connKey );
|
||||
if ( this.type != 'WebSite' ) {
|
||||
this.streamCmdReq.send( this.streamCmdParms+"&command="+CMD_QUERY );
|
||||
}
|
||||
};
|
||||
|
||||
if ( this.type != 'WebSite' ) {
|
||||
this.streamCmdReq = new Request.JSON( {
|
||||
url: this.server_url,
|
||||
method: 'get',
|
||||
|
@ -150,9 +162,10 @@ function Monitor( monitorData ) {
|
|||
onFailure: this.onFailure.bind(this),
|
||||
link: 'cancel'
|
||||
} );
|
||||
|
||||
console.log("queueing for " + this.id + " " + this.connKey );
|
||||
requestQueue.addRequest( "cmdReq"+this.id, this.streamCmdReq );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function selectLayout( element ) {
|
||||
|
@ -378,15 +391,26 @@ function cancel_layout(button) {
|
|||
selectLayout('#zmMontageLayout');
|
||||
}
|
||||
|
||||
function reloadWebSite(ndx) {
|
||||
document.getElementById('imageFeed'+ndx).innerHTML = document.getElementById('imageFeed'+ndx).innerHTML;
|
||||
}
|
||||
|
||||
var monitors = new Array();
|
||||
function initPage() {
|
||||
console.log("initPage");
|
||||
for ( var i = 0; i < monitorData.length; i++ ) {
|
||||
monitors[i] = new Monitor(monitorData[i]);
|
||||
var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout );
|
||||
var interval = monitors[i].refresh;
|
||||
monitors[i].start( delay );
|
||||
if ( monitors[i].type == 'WebSite' && interval > 0 ) {
|
||||
setInterval(reloadWebSite, interval*1000, i);
|
||||
}
|
||||
}
|
||||
selectLayout('#zmMontageLayout');
|
||||
|
||||
for ( var i = 0; i < monitorData.length; i++ ) {
|
||||
if ( monitors[i].type == 'WebSite' )
|
||||
continue;
|
||||
var delay = Math.round( (Math.random()+0.75)*statusRefreshTimeout );
|
||||
console.log("Delay for monitor " + monitorData[i].id + " is " + delay );
|
||||
monitors[i].streamCmdQuery.delay( delay, monitors[i] );
|
||||
|
|
|
@ -36,7 +36,9 @@ monitorData[monitorData.length] = {
|
|||
'width': <?php echo $monitor->Width() ?>,
|
||||
'height':<?php echo $monitor->Height() ?>,
|
||||
'server_url': '<?php echo $monitor->Server()->Url().$_SERVER['PHP_SELF'] ?>',
|
||||
'onclick': function(){createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?> );}
|
||||
'onclick': function(){createPopup( '?view=watch&mid=<?php echo $monitor->Id() ?>', 'zmWatch<?php echo $monitor->Id() ?>', 'watch', <?php echo reScale( $monitor->Width(), $monitor->PopupScale() ); ?>, <?php echo reScale( $monitor->Height(), $monitor->PopupScale() ); ?> );},
|
||||
'type': '<?php echo $monitor->Type() ?>',
|
||||
'refresh': '<?php echo $monitor->Refresh() ?>'
|
||||
};
|
||||
<?php
|
||||
} // end foreach monitor
|
||||
|
|
|
@ -105,18 +105,20 @@ function setAlarmState( currentAlarmState ) {
|
|||
lastAlarmState = alarmState;
|
||||
}
|
||||
|
||||
var streamCmdParms = "view=request&request=stream&connkey="+connKey;
|
||||
if ( auth_hash )
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var streamCmdParms = "view=request&request=stream&connkey="+connKey;
|
||||
if ( auth_hash )
|
||||
streamCmdParms += '&auth='+auth_hash;
|
||||
var streamCmdReq = new Request.JSON( {
|
||||
var streamCmdReq = new Request.JSON( {
|
||||
url: monitorUrl+thisUrl,
|
||||
method: 'get',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'chain',
|
||||
onSuccess: getStreamCmdResponse,
|
||||
onFailure: getStreamCmdFailure
|
||||
} );
|
||||
var streamCmdTimer = null;
|
||||
} );
|
||||
var streamCmdTimer = null;
|
||||
}
|
||||
|
||||
var streamStatus;
|
||||
|
||||
|
@ -350,11 +352,13 @@ function streamCmdQuery() {
|
|||
streamCmdReq.send( streamCmdParms+"&command="+CMD_QUERY );
|
||||
}
|
||||
|
||||
var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate";
|
||||
if ( auth_hash )
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
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: 'get', data: statusCmdParms, timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getStatusCmdResponse } );
|
||||
var statusCmdTimer = null;
|
||||
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 ) {
|
||||
watchdogOk("status");
|
||||
|
@ -377,18 +381,20 @@ function statusCmdQuery() {
|
|||
statusCmdReq.send();
|
||||
}
|
||||
|
||||
var alarmCmdParms = "view=request&request=alarm&id="+monitorId;
|
||||
if ( auth_hash )
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var alarmCmdParms = "view=request&request=alarm&id="+monitorId;
|
||||
if ( auth_hash )
|
||||
alarmCmdParms += '&auth='+auth_hash;
|
||||
var alarmCmdReq = new Request.JSON( {
|
||||
var alarmCmdReq = new Request.JSON( {
|
||||
url: monitorUrl+thisUrl,
|
||||
method: 'post',
|
||||
timeout: AJAX_TIMEOUT,
|
||||
link: 'cancel',
|
||||
onSuccess: getAlarmCmdResponse,
|
||||
onTimeout: streamCmdQuery
|
||||
} );
|
||||
var alarmCmdFirst = true;
|
||||
} );
|
||||
var alarmCmdFirst = true;
|
||||
}
|
||||
|
||||
function getAlarmCmdResponse( respObj, respText ) {
|
||||
checkStreamForErrors("getAlarmCmdResponse", respObj);
|
||||
|
@ -428,12 +434,14 @@ function deleteEvent( event, eventId ) {
|
|||
event.stop();
|
||||
}
|
||||
|
||||
var eventCmdParms = "view=request&request=status&entity=events&id="+monitorId+"&count="+maxDisplayEvents+"&sort=Id%20desc";
|
||||
if ( auth_hash )
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var eventCmdParms = "view=request&request=status&entity=events&id="+monitorId+"&count="+maxDisplayEvents+"&sort=Id%20desc";
|
||||
if ( auth_hash )
|
||||
eventCmdParms += '&auth='+auth_hash;
|
||||
var eventCmdReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, data: eventCmdParms, link: 'cancel', onSuccess: getEventCmdResponse, onTimeout: eventCmdQuery } );
|
||||
var eventCmdTimer = null;
|
||||
var eventCmdFirst = true;
|
||||
var eventCmdReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, data: eventCmdParms, link: 'cancel', onSuccess: getEventCmdResponse, onTimeout: eventCmdQuery } );
|
||||
var eventCmdTimer = null;
|
||||
var eventCmdFirst = true;
|
||||
}
|
||||
|
||||
function highlightRow( row ) {
|
||||
$(row).toggleClass( 'highlight' );
|
||||
|
@ -536,10 +544,12 @@ function eventCmdQuery() {
|
|||
eventCmdReq.send();
|
||||
}
|
||||
|
||||
var controlParms = "view=request&request=control&id="+monitorId;
|
||||
if ( auth_hash )
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
var controlParms = "view=request&request=control&id="+monitorId;
|
||||
if ( auth_hash )
|
||||
controlParms += '&auth='+auth_hash;
|
||||
var controlReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getControlResponse } );
|
||||
var controlReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getControlResponse } );
|
||||
}
|
||||
|
||||
function getControlResponse( respObj, respText ) {
|
||||
if ( !respObj )
|
||||
|
@ -652,6 +662,7 @@ function watchdogOk( type ) {
|
|||
}
|
||||
|
||||
function initPage() {
|
||||
if ( monitorType != 'WebSite' ) {
|
||||
if ( streamMode == "single" ) {
|
||||
statusCmdTimer = statusCmdQuery.delay( (Math.random()+0.1)*statusRefreshTimeout );
|
||||
watchdogCheck.pass('status').periodical(statusRefreshTimeout*2);
|
||||
|
@ -680,6 +691,9 @@ function initPage() {
|
|||
if (window.history.length == 1) {
|
||||
$j('#closeControl').html('');
|
||||
}
|
||||
} else if ( monitorRefresh > 0 ) {
|
||||
var myReload = setInterval(reloadWebSite, monitorRefresh*1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Kick everything off
|
||||
|
|
|
@ -49,6 +49,8 @@ var monitorId = <?php echo $monitor->Id() ?>;
|
|||
var monitorWidth = <?php echo $monitor->Width() ?>;
|
||||
var monitorHeight = <?php echo $monitor->Height() ?>;
|
||||
var monitorUrl = '<?php echo ( $monitor->Server()->Url() . ( ZM_MIN_STREAMING_PORT ? ':'. (ZM_MIN_STREAMING_PORT+$monitor->Id()) : '' ) ) ?>';
|
||||
var monitorType = '<?php echo ( $monitor->Type() ) ?>';
|
||||
var monitorRefresh = '<?php echo ( $monitor->Refresh() ) ?>';
|
||||
|
||||
var scale = '<?php echo $scale ?>';
|
||||
|
||||
|
|
|
@ -26,23 +26,6 @@ if ( !canView( 'Monitors' ) ) {
|
|||
return;
|
||||
}
|
||||
|
||||
$tabs = array();
|
||||
$tabs['general'] = translate('General');
|
||||
$tabs['source'] = translate('Source');
|
||||
$tabs['storage'] = translate('Storage');
|
||||
$tabs['timestamp'] = translate('Timestamp');
|
||||
$tabs['buffers'] = translate('Buffers');
|
||||
if ( ZM_OPT_CONTROL && canView( 'Control' ) )
|
||||
$tabs['control'] = translate('Control');
|
||||
if ( ZM_OPT_X10 )
|
||||
$tabs['x10'] = translate('X10');
|
||||
$tabs['misc'] = translate('Misc');
|
||||
|
||||
if ( isset($_REQUEST['tab']) )
|
||||
$tab = validHtmlStr($_REQUEST['tab']);
|
||||
else
|
||||
$tab = 'general';
|
||||
|
||||
$Server = null;
|
||||
if ( defined( 'ZM_SERVER_ID' ) ) {
|
||||
$Server = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( ZM_SERVER_ID ) );
|
||||
|
@ -142,6 +125,7 @@ if ( ! $monitor ) {
|
|||
'V4LCapturesPerFrame' => 1,
|
||||
'ServerId' => 'auto',
|
||||
'StorageId' => '1',
|
||||
'Refresh' => '',
|
||||
) );
|
||||
} # end if $_REQUEST['dupID']
|
||||
} # end if $_REQUEST['mid']
|
||||
|
@ -212,6 +196,7 @@ $sourceTypes = array(
|
|||
'Ffmpeg' => translate('Ffmpeg'),
|
||||
'Libvlc' => translate('Libvlc'),
|
||||
'cURL' => 'cURL (HTTP(S) only)',
|
||||
'WebSite'=> 'Web Site',
|
||||
'NVSocket' => translate('NVSocket')
|
||||
);
|
||||
if ( !ZM_HAS_V4L )
|
||||
|
@ -507,6 +492,25 @@ if ( canEdit( 'Monitors' ) ) {
|
|||
<div id="content">
|
||||
<ul class="tabList">
|
||||
<?php
|
||||
$tabs = array();
|
||||
$tabs['general'] = translate('General');
|
||||
$tabs['source'] = translate('Source');
|
||||
if ( $monitor->Type() != 'WebSite' ) {
|
||||
$tabs['storage'] = translate('Storage');
|
||||
$tabs['timestamp'] = translate('Timestamp');
|
||||
$tabs['buffers'] = translate('Buffers');
|
||||
if ( ZM_OPT_CONTROL && canView( 'Control' ) )
|
||||
$tabs['control'] = translate('Control');
|
||||
if ( ZM_OPT_X10 )
|
||||
$tabs['x10'] = translate('X10');
|
||||
$tabs['misc'] = translate('Misc');
|
||||
}
|
||||
|
||||
if ( isset($_REQUEST['tab']) )
|
||||
$tab = validHtmlStr($_REQUEST['tab']);
|
||||
else
|
||||
$tab = 'general';
|
||||
|
||||
foreach ( $tabs as $name=>$value ) {
|
||||
if ( $tab == $name ) {
|
||||
?>
|
||||
|
@ -583,7 +587,7 @@ if ( $tab != 'source' || ($monitor->Type()!= 'Ffmpeg' && $monitor->Type()!= 'Lib
|
|||
<input type="hidden" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/>
|
||||
<?php
|
||||
}
|
||||
if ( $tab != 'source' || ($monitor->Type()!= 'Remote' && $monitor->Type()!= 'File' && $monitor->Type()!= 'Ffmpeg' && $monitor->Type()!= 'Libvlc' && $monitor->Type()!= 'cURL') ) {
|
||||
if ( $tab != 'source' || ($monitor->Type()!= 'Remote' && $monitor->Type()!= 'File' && $monitor->Type()!= 'Ffmpeg' && $monitor->Type()!= 'Libvlc' && $monitor->Type()!= 'cURL' && $monitor->Type() != 'WebSite') ) {
|
||||
?>
|
||||
<input type="hidden" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>"/>
|
||||
<input type="hidden" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>"/>
|
||||
|
@ -713,6 +717,9 @@ switch ( $tab ) {
|
|||
?>
|
||||
</select></td></tr>
|
||||
<tr><td><?php echo translate('Enabled') ?></td><td><input type="checkbox" name="newMonitor[Enabled]" value="1"<?php if ( $monitor->Enabled() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
<?php
|
||||
if ( $monitor->Type != 'WebSite' ) {
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo translate('LinkedMonitors') ?></td>
|
||||
<td>
|
||||
|
@ -802,6 +809,7 @@ echo htmlOptions(Group::get_dropdown_options( ), $monitor->GroupIds() );
|
|||
?>
|
||||
</td></tr>
|
||||
<?php
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'source' :
|
||||
|
@ -868,6 +876,13 @@ include('_monitor_source_nvsocket.php');
|
|||
<tr><td><?php echo 'URL' ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo 'Username' ?></td><td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>" size="12"/></td></tr>
|
||||
<tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>" size="12"/></td></tr>
|
||||
<?php
|
||||
} elseif ( $monitor->Type() == 'WebSite' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('WebSiteUrl') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
|
||||
<tr><td><?php echo translate('Width') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4";"/></td></tr>
|
||||
<tr><td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4";"/></td></tr>
|
||||
<tr><td><?php echo 'Web Site Refresh (Optional)' ?></td><td><input type="number" name="newMonitor[Refresh]" value="<?php echo $monitor->Refresh()?>"/></td></tr>
|
||||
<?php
|
||||
} elseif ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) {
|
||||
?>
|
||||
|
@ -876,7 +891,7 @@ include('_monitor_source_nvsocket.php');
|
|||
<tr><td><?php echo translate('Options') ?> (<?php echo makePopupLink( '?view=optionhelp&option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>" size="36"/></td></tr>
|
||||
<?php
|
||||
}
|
||||
if ( $monitor->Type() != 'NVSocket' ) {
|
||||
if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('TargetColorspace') ?></td><td><?php echo htmlSelect('newMonitor[Colours]', $Colours, $monitor->Colours() ); ?>
|
||||
</td></tr>
|
||||
|
@ -890,7 +905,7 @@ if ( $monitor->Type() == 'Local' ) {
|
|||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts_v4l2 as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Deinterlacing()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
} else {
|
||||
} else if ( $monitor->Type() != 'WebSite' ) {
|
||||
?>
|
||||
<tr><td><?php echo translate('Deinterlacing') ?></td><td><select name="newMonitor[Deinterlacing]"><?php foreach ( $deinterlaceopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->Deinterlacing()) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
|
|
|
@ -204,7 +204,11 @@ foreach ( $monitors as $monitor ) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( $monitor->Type() == "WebSite" ) {
|
||||
echo getWebSiteUrl( 'liveStream'.$monitor->Id(), $monitor->Path(), reScale( $monitor->Width(), $scale ), reScale( $monitor->Height(), $scale ), $monitor->Name() );
|
||||
} else {
|
||||
echo getStreamHTML( $monitor, $monitor_options );
|
||||
}
|
||||
if ( $showZones ) {
|
||||
$height = null;
|
||||
$width = null;
|
||||
|
@ -255,7 +259,7 @@ foreach ( $monitors as $monitor ) {
|
|||
<?php } # end if showZones ?>
|
||||
</div>
|
||||
<?php
|
||||
if ( !ZM_WEB_COMPACT_MONTAGE ) {
|
||||
if ( (!ZM_WEB_COMPACT_MONTAGE) && ($monitor->Type() != 'WebSite') ) {
|
||||
?>
|
||||
<div id="monitorState<?php echo $monitor->Id() ?>" class="monitorState idle"><?php echo translate('State') ?>: <span id="stateValue<?php echo $monitor->Id() ?>"></span> - <span id="fpsValue<?php echo $monitor->Id() ?>"></span> fps</div>
|
||||
<?php
|
||||
|
|
|
@ -207,7 +207,7 @@ $frameSql .= ' ORDER BY Id DESC';
|
|||
|
||||
$monitors = array();
|
||||
foreach( $displayMonitors as $row ) {
|
||||
if ( $row['Function'] == 'None' )
|
||||
if ( $row['Function'] == 'None' || $row['Type'] == 'WebSite' )
|
||||
continue;
|
||||
$Monitor = new Monitor( $row );
|
||||
$monitors[] = $Monitor;
|
||||
|
|
|
@ -234,7 +234,7 @@ foreach( array_map( 'basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
|
|||
<td class="colMemory
|
||||
<?php if ( $row['FreeMem']/$row['TotalMem'] < .1 ) { echo 'danger'; } ?>"><?php echo makePopupLink( '?view=server&id='.$row['Id'], 'zmServer', 'server', human_filesize($row['FreeMem']) . ' / ' . human_filesize($row['TotalMem']), $canEdit ) ?></td>
|
||||
<td class="colSwap
|
||||
<?php if ( $row['FreeSwap']/$row['TotalSwap'] < .1 ) { echo 'danger'; } ?>"><?php echo makePopupLink( '?view=server&id='.$row['Id'], 'zmServer', 'server', human_filesize($row['FreeSwap']) . ' / ' . human_filesize($row['TotalSwap']) , $canEdit ) ?></td>
|
||||
<?php if ( (!$row['TotalSwap']) or ($row['FreeSwap']/$row['TotalSwap'] < .1) ) { echo 'danger'; } ?>"><?php echo makePopupLink( '?view=server&id='.$row['Id'], 'zmServer', 'server', human_filesize($row['FreeSwap']) . ' / ' . human_filesize($row['TotalSwap']) , $canEdit ) ?></td>
|
||||
<td class="colStats"><?php echo makePopupLink( '?view=server&id='.$row['Id'], 'zmServer', 'server', $row['zmstats'] ? 'yes' : 'no', $canEdit ) ?></td>
|
||||
<td class="colAudit"><?php echo makePopupLink( '?view=server&id='.$row['Id'], 'zmServer', 'server', $row['zmaudit'] ? 'yes' : 'no', $canEdit ) ?></td>
|
||||
<td class="colTrigger"><?php echo makePopupLink( '?view=server&id='.$row['Id'], 'zmServer', 'server', $row['zmtrigger'] ? 'yes' : 'no', $canEdit ) ?></td>
|
||||
|
@ -265,21 +265,22 @@ foreach( array_map( 'basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI
|
|||
<th class="colType"><?php echo translate('Type') ?></th>
|
||||
<th class="colScheme"><?php echo translate('StorageScheme') ?></th>
|
||||
<th class="colServer"><?php echo translate('Server') ?></th>
|
||||
<th class="colDiskSpace"><?php echo translate('DiskSpace') ?></th>
|
||||
<th class="colMark"><?php echo translate('Mark') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach( dbFetchAll( 'SELECT * FROM Storage ORDER BY Name' ) as $row ) { ?>
|
||||
<?php foreach( Storage::find_all( null, array('order'=>'lower(Name)') ) as $Storage ) { ?>
|
||||
<tr>
|
||||
<td class="colId"><?php echo makePopupLink( '?view=storage&id='.$row['Id'], 'zmStorage', 'storage', validHtmlStr($row['Id']), $canEdit ) ?></td>
|
||||
<td class="colName"><?php echo makePopupLink( '?view=storage&id='.$row['Id'], 'zmStorage', 'storage', validHtmlStr($row['Name']), $canEdit ) ?></td>
|
||||
<td class="colPath"><?php echo makePopupLink( '?view=storage&id='.$row['Id'], 'zmStorage', 'storage', validHtmlStr($row['Path']), $canEdit ) ?></td>
|
||||
<td class="colType"><?php echo makePopupLink( '?view=storage&id='.$row['Id'], 'zmStorage', 'storage', validHtmlStr($row['Type']), $canEdit ) ?></td>
|
||||
<td class="colScheme"><?php echo makePopupLink( '?view=storage&id='.$row['Id'], 'zmStorage', 'storage', validHtmlStr($row['Scheme']), $canEdit ) ?></td>
|
||||
<td class="colId"><?php echo makePopupLink('?view=storage&id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Id()), $canEdit ) ?></td>
|
||||
<td class="colName"><?php echo makePopupLink( '?view=storage&id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Name()), $canEdit ) ?></td>
|
||||
<td class="colPath"><?php echo makePopupLink( '?view=storage&id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Path()), $canEdit ) ?></td>
|
||||
<td class="colType"><?php echo makePopupLink( '?view=storage&id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Type()), $canEdit ) ?></td>
|
||||
<td class="colScheme"><?php echo makePopupLink( '?view=storage&id='.$Storage->Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Scheme()), $canEdit ) ?></td>
|
||||
<td class="colServer"><?php
|
||||
$Server = new Server($row['ServerId']);
|
||||
echo makePopupLink( '?view=storage&id='.$row['Id'], 'zmStorage', 'storage', validHtmlStr($Server->Name()), $canEdit ) ?></td>
|
||||
<td class="colMark"><input type="checkbox" name="markIds[]" value="<?php echo $row['Id'] ?>" onclick="configureDeleteButton(this);"<?php if ( !$canEdit ) { ?> disabled="disabled"<?php } ?>/></td>
|
||||
echo makePopupLink( '?view=storage&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="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 ?>
|
||||
</tbody>
|
||||
|
|
|
@ -102,6 +102,7 @@ while( $event = $result->fetch(PDO::FETCH_ASSOC) ) {
|
|||
|
||||
if ( count($EventsByMonitor[$event['MonitorId']]['Events']) ) {
|
||||
$last_event = end($EventsByMonitor[$event['MonitorId']]['Events']);
|
||||
#Logger::Debug(print_r($last_event,true));
|
||||
$gap = $last_event->EndTimeSecs() - $event['StartTimeSecs'];
|
||||
|
||||
if ( $gap < $EventsByMonitor[$event['MonitorId']]['MinGap'] )
|
||||
|
@ -140,7 +141,10 @@ while( $event = $result->fetch(PDO::FETCH_ASSOC) ) {
|
|||
<tr>
|
||||
<th class="colId"><?php echo translate('Id') ?></th>
|
||||
<th class="colName"><i class="material-icons md-18">videocam</i> <?php echo translate('Name') ?></th>
|
||||
<th class="colServer"><?php echo translate('Server') ?></th>
|
||||
<th class="colEvents"><?php echo translate('Events') ?></th>
|
||||
<th class="colFirstEvent"><?php echo translate('FirstEvent') ?></th>
|
||||
<th class="colLastEvent"><?php echo translate('LastEvent') ?></th>
|
||||
<th class="colMinGap"><?php echo translate('MinGap') ?></th>
|
||||
<th class="colMaxGap"><?php echo translate('MaxGap') ?></th>
|
||||
<th class="colMissingFiles"><?php echo translate('MissingFiles') ?></th>
|
||||
|
@ -152,8 +156,25 @@ while( $event = $result->fetch(PDO::FETCH_ASSOC) ) {
|
|||
for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
||||
$monitor = $displayMonitors[$monitor_i];
|
||||
$Monitor = new Monitor($monitor);
|
||||
|
||||
$montagereview_link = "?view=montagereview&live=0&MonitorId=". $monitor['Id'] . '&minTime='.$minTime.'&maxTime='.$maxTime;
|
||||
|
||||
if ( isset($EventsByMonitor[$Monitor->Id()]) ) {
|
||||
$EventCounts = $EventsByMonitor[$Monitor->Id()];
|
||||
$MinGap = $EventCounts['MinGap'];
|
||||
$MaxGap = $EventCounts['MaxGap'];
|
||||
$FileMissing = $EventCounts['FileMissing'];
|
||||
$ZeroSize = $EventCounts['ZeroSize'];
|
||||
$FirstEvent = $EventCounts['Events'][0];
|
||||
$LastEvent = end($EventCounts['Events']);
|
||||
} else {
|
||||
$MinGap = 0;
|
||||
$MaxGap = 0;
|
||||
$FileMissing = 0;
|
||||
$ZeroSize = 0;
|
||||
$FirstEvent = 0;
|
||||
$LastEvent = 0;
|
||||
}
|
||||
|
||||
?>
|
||||
<tr id="<?php echo 'monitor_id-'.$monitor['Id'] ?>" title="<?php echo $monitor['Id'] ?>">
|
||||
<td class="colId"><a href="<?php echo $montagereview_link ?>"><?php echo $monitor['Id'] ?></a></td>
|
||||
|
@ -168,11 +189,14 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
}, $Monitor->GroupIds() ) );
|
||||
?>
|
||||
</div></td>
|
||||
<td class="colServer"><?php echo $Monitor->Server()->Name()?></td>
|
||||
<td class="colEvents"><?php echo isset($EventsByMonitor[$Monitor->Id()])?count($EventsByMonitor[$Monitor->Id()]['Events']):0 ?></td>
|
||||
<td class="colMinGap"><?php echo isset($EventsByMonitor[$Monitor->Id()])?$EventsByMonitor[$Monitor->Id()]['MinGap']:0 ?></td>
|
||||
<td class="colMaxGap"><?php echo isset($EventsByMonitor[$Monitor->Id()])?$EventsByMonitor[$Monitor->Id()]['MaxGap']:0 ?></td>
|
||||
<td class="colFileMissing"><?php echo isset($EventsByMonitor[$Monitor->Id()])?$EventsByMonitor[$Monitor->Id()]['FileMissing']:0 ?></td>
|
||||
<td class="colZeroSize"><?php echo isset($EventsByMonitor[$Monitor->Id()])?$EventsByMonitor[$Monitor->Id()]['ZeroSize']:0 ?></td>
|
||||
<td class="colFirstEvent"><?php echo $FirstEvent ? $FirstEvent->link_to($FirstEvent->Id().' at ' . $FirstEvent->StartTime()) : 'none'?></td>
|
||||
<td class="colLastEvent"><?php echo $LastEvent ? $LastEvent->link_to($LastEvent->Id().' at ' . $LastEvent->StartTime()) : 'none'?></td>
|
||||
<td class="colMinGap"><?php echo $MinGap ?></td>
|
||||
<td class="colMaxGap"><?php echo $MaxGap ?></td>
|
||||
<td class="colFileMissing<?php echo $FileMissing ? ' errorText' : ''?>"><?php echo $FileMissing ?></td>
|
||||
<td class="colZeroSize<?php echo $ZeroSize ? ' errorText' : ''?>"><?php echo $ZeroSize ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
} # end for each monitor
|
||||
|
|
|
@ -41,7 +41,7 @@ if ( ! visibleMonitor( $mid ) ) {
|
|||
$monitor = new Monitor( $mid );
|
||||
|
||||
#Whether to show the controls button
|
||||
$showPtzControls = ( ZM_OPT_CONTROL && $monitor->Controllable() && canView( 'Control' ) );
|
||||
$showPtzControls = ( ZM_OPT_CONTROL && $monitor->Controllable() && canView('Control') && $monitor->Type() != 'WebSite' );
|
||||
|
||||
if ( isset( $_REQUEST['scale'] ) ) {
|
||||
$scale = validInt($_REQUEST['scale']);
|
||||
|
@ -80,6 +80,7 @@ if ( canView( 'Control' ) && $monitor->Type() == 'Local' ) {
|
|||
</div>
|
||||
<div id="content">
|
||||
<div id="imageFeed"><?php echo getStreamHTML( $monitor, array('scale'=>$scale) ); ?></div>
|
||||
<?php if ( $monitor->Type() != 'WebSite' ) { ?>
|
||||
<div id="monitorStatus">
|
||||
<?php if ( canEdit( 'Monitors' ) ) { ?>
|
||||
<div id="enableDisableAlarms"><a id="enableAlarmsLink" href="#" onclick="cmdEnableAlarms(); return( false );" class="hidden"><?php echo translate('EnableAlarms') ?></a><a id="disableAlarmsLink" href="#" onclick="cmdDisableAlarms(); return( false );" class="hidden"><?php echo translate('DisableAlarms') ?></a></div>
|
||||
|
@ -119,7 +120,7 @@ if ( $streamMode == 'jpeg' ) {
|
|||
?>
|
||||
<input type="button" value="–" id="zoomOutBtn" title="<?php echo translate('ZoomOut') ?>" class="avail" onclick="streamCmdZoomOut()"/>
|
||||
<?php
|
||||
} // end if streamMode==jpeg
|
||||
} // end if streamMode==jpeg
|
||||
?>
|
||||
</div>
|
||||
<div id="replayStatus"<?php echo $streamMode=="single"?' class="hidden"':'' ?>>
|
||||
|
@ -129,6 +130,7 @@ if ( $streamMode == 'jpeg' ) {
|
|||
<span id="level"><?php echo translate('Buffer') ?>: <span id="levelValue"></span>%</span>
|
||||
<span id="zoom"><?php echo translate('Zoom') ?>: <span id="zoomValue"></span>x</span>
|
||||
</div>
|
||||
<?php } // end if $monitor->Type() != 'WebSite' ?>
|
||||
<?php
|
||||
if ( $showPtzControls ) {
|
||||
foreach ( getSkinIncludes( 'includes/control_functions.php' ) as $includeFile )
|
||||
|
@ -139,7 +141,7 @@ if ( $showPtzControls ) {
|
|||
</div>
|
||||
<?php
|
||||
}
|
||||
if ( canView( 'Events' ) ) {
|
||||
if ( canView( 'Events' ) && $monitor->Type() != 'WebSite' ) {
|
||||
?>
|
||||
<div id="events">
|
||||
<table id="eventList" cellspacing="0">
|
||||
|
|
Loading…
Reference in New Issue