Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas
This commit is contained in:
commit
f3d3357365
|
@ -233,6 +233,8 @@ CREATE TABLE `Filters` (
|
|||
`AutoExecute` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoExecuteCmd` tinytext,
|
||||
`AutoDelete` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoMove` tinyint(3) unsigned NOT NULL default '0',
|
||||
`AutoMoveTo` smallint(5) unsigned NOT NULL default 0,
|
||||
`UpdateDiskSpace` tinyint(3) unsigned NOT NULL default '0',
|
||||
`Background` tinyint(1) unsigned NOT NULL default '0',
|
||||
`Concurrent` tinyint(1) unsigned NOT NULL default '0',
|
||||
|
@ -268,10 +270,24 @@ CREATE TABLE `Groups` (
|
|||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`Name` varchar(64) NOT NULL default '',
|
||||
`ParentId` int(10) unsigned,
|
||||
`MonitorIds` text NOT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
--
|
||||
--Table structure for table `Groups_Monitors`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `Groups_Monitors`
|
||||
CREATE TABLE `Groups_Monitors` (
|
||||
`Id` INT(10) unsigned NOT NULL auto_increment,
|
||||
`GroupId` int(10) unsigned NOT NULL,
|
||||
`MonitorId` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=@ZM_MYSQL_ENGINE@;
|
||||
|
||||
CREATE INDEX `Groups_Monitors_GroupId_idx` ON `Groups` (`GroupId`);
|
||||
CREATE INDEX `Groups_Monitors_MonitorId_idx` ON `Groups` (`MonitorId`);
|
||||
|
||||
--
|
||||
-- Table structure for table `Logs`
|
||||
--
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
--
|
||||
-- Add UpdateDiskSpace action to Filters
|
||||
--
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Filters'
|
||||
AND column_name = 'AutoMove'
|
||||
) > 0,
|
||||
"SELECT 'Column AutoMove already exists in Filters'",
|
||||
"ALTER TABLE Filters ADD `AutoMove` tinyint(3) unsigned NOT NULL default '0' AFTER `AutoDelete`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Filters'
|
||||
AND column_name = 'AutoMoveTo'
|
||||
) > 0,
|
||||
"SELECT 'Column AutoMoveTo already exists in Filters'",
|
||||
"ALTER TABLE Filters ADD `AutoMoveTo` smallint(5) unsigned NOT NULL default '0' AFTER `AutoMove`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE table_name = 'Groups_Monitors'
|
||||
AND table_schema = DATABASE()
|
||||
) > 0,
|
||||
"SELECT 'Groups_Monitors table exists'",
|
||||
"CREATE TABLE `Groups_Monitors` (
|
||||
`Id` INT(10) unsigned NOT NULL auto_increment,
|
||||
`GroupId` int(10) unsigned NOT NULL,
|
||||
`MonitorId` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE table_name = 'Groups_Monitors'
|
||||
AND table_schema = DATABASE()
|
||||
AND index_name = 'Groups_Monitors_GroupId_idx'
|
||||
) > 0,
|
||||
"SELECT 'Groups_Monitors_GroupId_idx already exists on Groups table'",
|
||||
"CREATE INDEX `Groups_Monitors_GroupId_idx` ON `Groups_Monitors` (`GroupId`)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.STATISTICS
|
||||
WHERE table_name = 'Groups_Monitors'
|
||||
AND table_schema = DATABASE()
|
||||
AND index_name = 'Groups_Monitors_MonitorId_idx'
|
||||
) > 0,
|
||||
"SELECT 'Groups_Monitors_MonitorId_idx already exists on Groups table'",
|
||||
"CREATE INDEX `Groups_Monitors_MonitorId_idx` ON `Groups_Monitors` (`MonitorId`)"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Groups'
|
||||
AND column_name = 'MonitorIds'
|
||||
) > 0,
|
||||
"REPLACE INTO Groups_Monitors (GroupId,MonitorId) SELECT Id,SUBSTRING_INDEX(SUBSTRING_INDEX(t.MonitorIds, ',', n.n), ',', -1) value FROM Groups t CROSS JOIN ( SELECT a.N + b.N * 10 + 1 n FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b ORDER BY n ) n WHERE t.MonitorIds != '' AND n.n <= 1 + (LENGTH(t.MonitorIds) - LENGTH(REPLACE(t.MonitorIds, ',', ''))) ORDER BY value;",
|
||||
"SELECT 'MonitorIds has already been removed.'"
|
||||
));
|
||||
/*
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Groups'
|
||||
AND column_name = 'MonitorIds'
|
||||
) > 0,
|
||||
"ALTER TABLE Groups DROP MonitorIds",
|
||||
"SELECT 'MonitorIds has already been removed.'"
|
||||
));
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
*/
|
|
@ -79,13 +79,13 @@ BEGIN {
|
|||
# Search for user created config files. If one or more are found then
|
||||
# update the Config hash with those values
|
||||
if ( -d ZM_CONFIG_SUBDIR ) {
|
||||
if ( -R ZM_CONFIG_SUBDIR ) {
|
||||
foreach my $filename ( glob ZM_CONFIG_SUBDIR."/*.conf" ) {
|
||||
process_configfile($filename);
|
||||
}
|
||||
} else {
|
||||
print( STDERR "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on ".ZM_CONFIG_SUBDIR.".\n" );
|
||||
if ( -R ZM_CONFIG_SUBDIR ) {
|
||||
foreach my $filename ( glob ZM_CONFIG_SUBDIR."/*.conf" ) {
|
||||
process_configfile($filename);
|
||||
}
|
||||
} else {
|
||||
print( STDERR "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on ".ZM_CONFIG_SUBDIR.".\n" );
|
||||
}
|
||||
}
|
||||
|
||||
use DBI;
|
||||
|
@ -94,14 +94,14 @@ BEGIN {
|
|||
|
||||
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",
|
||||
|
@ -123,7 +123,8 @@ BEGIN {
|
|||
}
|
||||
$sth->finish();
|
||||
#$dbh->disconnect();
|
||||
if ( ! exists $Config{ZM_SERVER_ID} ) {
|
||||
#
|
||||
if ( ! $Config{ZM_SERVER_ID} ) {
|
||||
$Config{ZM_SERVER_ID} = undef;
|
||||
$sth = $dbh->prepare_cached( 'SELECT * FROM Servers WHERE Name=?' );
|
||||
if ( $Config{ZM_SERVER_NAME} ) {
|
||||
|
@ -140,32 +141,32 @@ BEGIN {
|
|||
|
||||
# This subroutine must be inside the BEGIN block
|
||||
sub process_configfile {
|
||||
my $config_file = shift;
|
||||
my $config_file = shift;
|
||||
|
||||
if ( -R $config_file ) {
|
||||
open( my $CONFIG, "<", $config_file )
|
||||
or croak( "Can't open config file '$config_file': $!" );
|
||||
foreach my $str ( <$CONFIG> ) {
|
||||
next if ( $str =~ /^\s*$/ );
|
||||
next if ( $str =~ /^\s*#/ );
|
||||
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.*?)\s*$/;
|
||||
if ( ! $name ) {
|
||||
print( STDERR "Warning, bad line in $config_file: $str\n" );
|
||||
next;
|
||||
} # end if
|
||||
$name =~ tr/a-z/A-Z/;
|
||||
$Config{$name} = $value;
|
||||
}
|
||||
close( $CONFIG );
|
||||
} else {
|
||||
print( STDERR "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $config_file\n" );
|
||||
if ( -R $config_file ) {
|
||||
open( my $CONFIG, '<', $config_file )
|
||||
or croak( "Can't open config file '$config_file': $!" );
|
||||
foreach my $str ( <$CONFIG> ) {
|
||||
next if ( $str =~ /^\s*$/ );
|
||||
next if ( $str =~ /^\s*#/ );
|
||||
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.*?)\s*$/;
|
||||
if ( ! $name ) {
|
||||
print( STDERR "Warning, bad line in $config_file: $str\n" );
|
||||
next;
|
||||
} # end if
|
||||
$name =~ tr/a-z/A-Z/;
|
||||
$Config{$name} = $value;
|
||||
}
|
||||
close( $CONFIG );
|
||||
} else {
|
||||
print( STDERR "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $config_file\n" );
|
||||
}
|
||||
}
|
||||
|
||||
} # end BEGIN
|
||||
|
||||
sub loadConfigFromDB {
|
||||
print( "Loading config from DB" );
|
||||
print( 'Loading config from DB' );
|
||||
my $dbh = ZoneMinder::Database::zmDbConnect();
|
||||
if ( !$dbh ) {
|
||||
print( "Error: unable to load options from database: $DBI::errstr\n" );
|
||||
|
@ -188,7 +189,7 @@ sub loadConfigFromDB {
|
|||
#next if ( $option->{category} eq 'hidden' );
|
||||
if ( defined($value) ) {
|
||||
if ( $option->{type} == $types{boolean} ) {
|
||||
$option->{value} = $value?"yes":"no";
|
||||
$option->{value} = $value?'yes':'no';
|
||||
} else {
|
||||
$option->{value} = $value;
|
||||
}
|
||||
|
@ -201,7 +202,7 @@ sub loadConfigFromDB {
|
|||
} # end sub loadConfigFromDB
|
||||
|
||||
sub saveConfigToDB {
|
||||
print( "Saving config to DB " . @options . " entries\n" );
|
||||
print( 'Saving config to DB ' . @options . " entries\n" );
|
||||
my $dbh = ZoneMinder::Database::zmDbConnect();
|
||||
if ( !$dbh ) {
|
||||
print( "Error: unable to save options to database: $DBI::errstr\n" );
|
||||
|
@ -214,7 +215,7 @@ sub saveConfigToDB {
|
|||
$dbh->do('LOCK TABLE Config WRITE')
|
||||
or croak( "Can't lock Config table: " . $dbh->errstr() );
|
||||
|
||||
my $sql = "delete from Config";
|
||||
my $sql = 'DELETE FROM Config';
|
||||
my $res = $dbh->do( $sql )
|
||||
or croak( "Can't do '$sql': ".$dbh->errstr() );
|
||||
|
||||
|
@ -228,8 +229,8 @@ sub saveConfigToDB {
|
|||
$option->{db_hint} = $option->{type}->{hint};
|
||||
$option->{db_pattern} = $option->{type}->{pattern};
|
||||
$option->{db_format} = $option->{type}->{format};
|
||||
if ( $option->{db_type} eq "boolean" ) {
|
||||
$option->{db_value} = ($option->{value} eq "yes") ? "1" : "0";
|
||||
if ( $option->{db_type} eq 'boolean' ) {
|
||||
$option->{db_value} = ($option->{value} eq 'yes') ? '1' : '0';
|
||||
} else {
|
||||
$option->{db_value} = $option->{value};
|
||||
}
|
||||
|
@ -237,7 +238,7 @@ sub saveConfigToDB {
|
|||
$option->{db_requires} = join( ";",
|
||||
map {
|
||||
my $value = $_->{value};
|
||||
$value = ($value eq "yes") ? 1 : 0 if ( $options_hash{$_->{name}}->{db_type} eq "boolean" );
|
||||
$value = ($value eq 'yes') ? 1 : 0 if ( $options_hash{$_->{name}}->{db_type} eq 'boolean' );
|
||||
( "$_->{name}=$value" )
|
||||
} @$requires
|
||||
);
|
||||
|
|
|
@ -2933,6 +2933,16 @@ our @options = (
|
|||
type => $types{integer},
|
||||
category => 'highband',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_H_REFRESH_NAVBAR',
|
||||
default => '5',
|
||||
description => 'How often (in seconds) the navigation header should refresh itself',
|
||||
help => q`
|
||||
The navigation header contains the general status information about server load and storage space.
|
||||
`,
|
||||
type => $types{integer},
|
||||
category => 'highband',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_H_REFRESH_CYCLE',
|
||||
default => '10',
|
||||
|
@ -3196,6 +3206,16 @@ our @options = (
|
|||
`,
|
||||
category => 'medband',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_M_REFRESH_NAVBAR',
|
||||
default => '15',
|
||||
description => 'How often (in seconds) the navigation header should refresh itself',
|
||||
help => q`
|
||||
The navigation header contains the general status information about server load and storage space.
|
||||
`,
|
||||
type => $types{integer},
|
||||
category => 'medband',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_M_REFRESH_CYCLE',
|
||||
default => '20',
|
||||
|
@ -3459,6 +3479,16 @@ our @options = (
|
|||
type => $types{integer},
|
||||
category => 'lowband',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_L_REFRESH_NAVBAR',
|
||||
default => '35',
|
||||
description => 'How often (in seconds) the navigation header should refresh itself',
|
||||
help => q`
|
||||
The navigation header contains the general status information about server load and storage space.
|
||||
`,
|
||||
type => $types{integer},
|
||||
category => 'lowband',
|
||||
},
|
||||
{
|
||||
name => 'ZM_WEB_L_REFRESH_CYCLE',
|
||||
default => '30',
|
||||
|
|
|
@ -33,6 +33,8 @@ require ZoneMinder::Object;
|
|||
require ZoneMinder::Storage;
|
||||
require Date::Manip;
|
||||
require File::Find;
|
||||
require File::Path;
|
||||
require File::Copy;
|
||||
|
||||
#our @ISA = qw(ZoneMinder::Object);
|
||||
use parent qw(ZoneMinder::Object);
|
||||
|
@ -401,6 +403,54 @@ sub DiskSpace {
|
|||
}
|
||||
}
|
||||
|
||||
sub MoveTo {
|
||||
my ( $self, $NewStorage ) = @_;
|
||||
my ( $OldPath ) = ( $self->Path() =~ /^(.*)$/ ); # De-taint
|
||||
my ( $NewPath ) = ( $NewStorage->Path() =~ /^(.*)$/ ); # De-taint
|
||||
if ( ! $$NewStorage{Id} ) {
|
||||
return "New storage does not have an id. Moving will not happen.";
|
||||
} elsif ( !$NewPath) {
|
||||
return "$NewPath is empty.";
|
||||
}elsif ( $NewPath eq $OldPath ) {
|
||||
return "New path and old path are the same! $NewPath";
|
||||
} elsif ( ! -e $NewPath ) {
|
||||
return "New path $NewPath does not exist.";
|
||||
}elsif ( ! -e $OldPath ) {
|
||||
return "Old path $OldPath does not exist.";
|
||||
}
|
||||
|
||||
my $error = '';
|
||||
File::Path::make_path( $NewPath, {error => \my $err} );
|
||||
if ( @$err ) {
|
||||
for my $diag (@$err) {
|
||||
my ($file, $message) = %$diag;
|
||||
if ($file eq '') {
|
||||
$error .= "general error: $message\n";
|
||||
} else {
|
||||
$error .= "problem unlinking $file: $message\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $error if $error;
|
||||
my @files = glob("$OldPath/*");
|
||||
|
||||
for my $file (@files) {
|
||||
next if $file =~ /^\./;
|
||||
( $file ) = ( $file =~ /^(.*)$/ ); # De-taint
|
||||
if ( ! File::Copy::copy( $file, $NewPath ) ) {
|
||||
$error .= "Copy failed: for $file to $NewPath: $!";
|
||||
last;
|
||||
}
|
||||
} # end foreach file.
|
||||
|
||||
if ( ! $error ) {
|
||||
# Succeeded in copying all files, so we may now update the Event.
|
||||
$$self{StorageId} = $$NewStorage{Id};
|
||||
$error .= $self->save();
|
||||
}
|
||||
return $error;
|
||||
} # end sub MoveTo
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
|
|
|
@ -207,10 +207,11 @@ sub Sql {
|
|||
if ( $term->{attr} =~ /^Monitor/ ) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} eq 'ServerId' ) {
|
||||
Debug("ServerId, temp_value is ($temp_value) ($ZoneMinder::Config::Config{ZM_SERVER_ID})");
|
||||
if ( $temp_value eq 'ZM_SERVER_ID' ) {
|
||||
$value = "'$Config{ZM_SERVER_ID}'";
|
||||
$value = "'$ZoneMinder::Config::Config{ZM_SERVER_ID}'";
|
||||
# This gets used later, I forget for what
|
||||
$$self{Server} = new ZoneMinder::Server( $Config{ZM_SERVER_ID} );
|
||||
$$self{Server} = new ZoneMinder::Server( $ZoneMinder::Config::Config{ZM_SERVER_ID} );
|
||||
} else {
|
||||
$value = "'$temp_value'";
|
||||
# This gets used later, I forget for what
|
||||
|
@ -225,7 +226,7 @@ sub Sql {
|
|||
) {
|
||||
$value = "'$temp_value'";
|
||||
} elsif ( $term->{attr} eq 'DateTime' or $term->{attr} eq 'StartDateTime' or $term->{attr} eq 'EndDateTime' ) {
|
||||
if ( $temp_value == 'NULL' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
|
@ -237,7 +238,7 @@ sub Sql {
|
|||
$value = "'$value'";
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'Date' or $term->{attr} eq 'StartDate' or $term->{attr} eq 'EndDate' ) {
|
||||
if ( $temp_value == 'NULL' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
|
@ -249,7 +250,7 @@ sub Sql {
|
|||
$value = "to_days( '$value' )";
|
||||
}
|
||||
} elsif ( $term->{attr} eq 'Time' or $term->{attr} eq 'StartTime' or $term->{attr} eq 'EndTime' ) {
|
||||
if ( $temp_value == 'NULL' ) {
|
||||
if ( $temp_value eq 'NULL' ) {
|
||||
$value = $temp_value;
|
||||
} else {
|
||||
$value = DateTimeToSQL( $temp_value );
|
||||
|
|
|
@ -47,7 +47,7 @@ use vars qw/ $AUTOLOAD $log $dbh/;
|
|||
*log = \$ZoneMinder::Logger::logger;
|
||||
*dbh = \$ZoneMinder::Database::dbh;
|
||||
|
||||
my $debug = 1;
|
||||
my $debug = 0;
|
||||
use constant DEBUG_ALL=>1;
|
||||
|
||||
sub new {
|
||||
|
|
|
@ -207,7 +207,7 @@ sub getFilters {
|
|||
} else {
|
||||
$sql .= ' Background = 1 AND';
|
||||
}
|
||||
$sql .= '( AutoArchive = 1
|
||||
$sql .= '( AutoArchive = 1
|
||||
or AutoVideo = 1
|
||||
or AutoUpload = 1
|
||||
or AutoEmail = 1
|
||||
|
@ -215,16 +215,17 @@ sub getFilters {
|
|||
or AutoExecute = 1
|
||||
or AutoDelete = 1
|
||||
or UpdateDiskSpace = 1
|
||||
or AutoMove = 1
|
||||
) ORDER BY Name';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Unable toprepare '$sql': ".$dbh->errstr() );
|
||||
or Fatal( "Unable to prepare '$sql': ".$dbh->errstr() );
|
||||
my $res;
|
||||
if ( $filter_name ) {
|
||||
$res = $sth->execute( $filter_name )
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable to execute '$sql': ".$sth->errstr() );
|
||||
} else {
|
||||
$res = $sth->execute()
|
||||
or Fatal( "Unable toexecute '$sql': ".$sth->errstr() );
|
||||
or Fatal( "Unable to execute '$sql': ".$sth->errstr() );
|
||||
}
|
||||
FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) {
|
||||
my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter );
|
||||
|
@ -263,6 +264,7 @@ sub checkFilter {
|
|||
($filter->{AutoEmail}?'email':()),
|
||||
($filter->{AutoMessage}?'message':()),
|
||||
($filter->{AutoExecute}?'execute':()),
|
||||
($filter->{AutoMove}?'move':()),
|
||||
($filter->{UpdateDiskSpace}?'update disk space':()),
|
||||
),
|
||||
'returned' , scalar @Events , 'events',
|
||||
|
@ -270,12 +272,12 @@ sub checkFilter {
|
|||
) );
|
||||
|
||||
foreach my $event ( @Events ) {
|
||||
Debug( "Checking event $event->{Id}\n" );
|
||||
Debug( "Checking event $event->{Id}" );
|
||||
my $delete_ok = !undef;
|
||||
$dbh->ping();
|
||||
if ( $filter->{AutoArchive} ) {
|
||||
Info( "Archiving event $event->{Id}\n" );
|
||||
# Do it individually to avoid locking up the table for new events
|
||||
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() );
|
||||
|
@ -315,11 +317,17 @@ sub checkFilter {
|
|||
Error( "Unable toto delete event $event->{Id} as previous operations failed\n" );
|
||||
}
|
||||
} # end if AutoDelete
|
||||
if ( $filter->{AutoMove} ) {
|
||||
my $Event = new ZoneMinder::Event( $$event{Id}, $event );
|
||||
my $NewStorage = new ZoneMinder::Storage( $filter->{AutoMoveTo} );
|
||||
$_ = $Event->MoveTo( $NewStorage );
|
||||
Error($_) if $_;
|
||||
}
|
||||
|
||||
if ( $filter->{UpdateDiskSpace} ) {
|
||||
my $Event = new ZoneMinder::Event( $$event{Id}, $event );
|
||||
$Event->DiskSpace(undef);
|
||||
$Event->save();
|
||||
|
||||
my $Event = new ZoneMinder::Event( $$event{Id}, $event );
|
||||
$Event->DiskSpace(undef);
|
||||
$Event->save();
|
||||
} # end if UpdateDiskSpace
|
||||
} # end foreach event
|
||||
}
|
||||
|
|
|
@ -28,8 +28,9 @@ MYSQL dbconn;
|
|||
int zmDbConnected = false;
|
||||
|
||||
void zmDbConnect() {
|
||||
if ( zmDbConnected )
|
||||
return;
|
||||
// For some reason having these lines causes memory corruption and crashing on newer debian/ubuntu
|
||||
//if ( zmDbConnected )
|
||||
//return;
|
||||
|
||||
if ( !mysql_init( &dbconn ) ) {
|
||||
Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) );
|
||||
|
|
|
@ -190,7 +190,7 @@ int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat
|
|||
return ret;
|
||||
} else {
|
||||
s->oformat = oformat;
|
||||
#if 0
|
||||
#if 1
|
||||
// This is some very wrong code, and I don't think it is neccessary
|
||||
if (s->oformat->priv_data_size > 0) {
|
||||
s->priv_data = av_mallocz(s->oformat->priv_data_size);
|
||||
|
|
|
@ -328,6 +328,9 @@ int FfmpegCamera::PostCapture() {
|
|||
int FfmpegCamera::OpenFfmpeg() {
|
||||
|
||||
Debug ( 2, "OpenFfmpeg called." );
|
||||
uint32_t last_event_id = monitor->GetLastEventId() ;
|
||||
uint32_t video_writer_event_id = monitor->GetVideoWriterEventId();
|
||||
Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
|
||||
|
||||
int ret;
|
||||
|
||||
|
@ -372,6 +375,9 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
//FIXME can speed up initial analysis but need sensible parameters...
|
||||
//mFormatContext->probesize = 32;
|
||||
//mFormatContext->max_analyze_duration = 32;
|
||||
last_event_id = monitor->GetLastEventId() ;
|
||||
video_writer_event_id = monitor->GetVideoWriterEventId();
|
||||
Debug(2, "last_event(%d), our current (%d), mpath (%s)", last_event_id, video_writer_event_id, mPath.c_str() );
|
||||
|
||||
if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) != 0 )
|
||||
#endif
|
||||
|
@ -380,12 +386,18 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
Error( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
AVDictionaryEntry *e;
|
||||
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
last_event_id = monitor->GetLastEventId() ;
|
||||
video_writer_event_id = monitor->GetVideoWriterEventId();
|
||||
Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
|
||||
AVDictionaryEntry *e=NULL;
|
||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
Warning( "Option %s not recognized by ffmpeg", e->key);
|
||||
}
|
||||
|
||||
last_event_id = monitor->GetLastEventId() ;
|
||||
video_writer_event_id = monitor->GetVideoWriterEventId();
|
||||
Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
|
||||
|
||||
mIsOpening = false;
|
||||
Debug ( 1, "Opened input" );
|
||||
|
||||
|
@ -524,15 +536,15 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
Debug ( 1, "Calling avcodec_open2" );
|
||||
if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 ) {
|
||||
#endif
|
||||
AVDictionaryEntry *e;
|
||||
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
AVDictionaryEntry *e = NULL;
|
||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
Warning( "Option %s not recognized by ffmpeg", e->key);
|
||||
}
|
||||
Fatal( "Unable to open codec for video stream from %s", mPath.c_str() );
|
||||
} else {
|
||||
|
||||
AVDictionaryEntry *e;
|
||||
if ( (e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
AVDictionaryEntry *e = NULL;
|
||||
if ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
Warning( "Option %s not recognized by ffmpeg", e->key);
|
||||
}
|
||||
}
|
||||
|
@ -567,7 +579,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
}
|
||||
}
|
||||
|
||||
Debug ( 1, "Opened codec" );
|
||||
Debug ( 1, "Opened audio codec" );
|
||||
|
||||
// Allocate space for the native video frame
|
||||
mRawFrame = zm_av_frame_alloc();
|
||||
|
@ -666,12 +678,16 @@ int FfmpegCamera::CloseFfmpeg() {
|
|||
|
||||
if ( mVideoCodecContext ) {
|
||||
avcodec_close(mVideoCodecContext);
|
||||
//av_free(mVideoCodecContext);
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
avcodec_free_context(&mVideoCodecContext);
|
||||
#endif
|
||||
mVideoCodecContext = NULL; // Freed by av_close_input_file
|
||||
}
|
||||
if ( mAudioCodecContext ) {
|
||||
avcodec_close(mAudioCodecContext);
|
||||
//av_free(mAudioCodecContext);
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
avcodec_free_context(&mAudioCodecContext);
|
||||
#endif
|
||||
mAudioCodecContext = NULL; // Freed by av_close_input_file
|
||||
}
|
||||
|
||||
|
@ -780,9 +796,10 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
|||
if ( recording.tv_sec ) {
|
||||
|
||||
uint32_t last_event_id = monitor->GetLastEventId() ;
|
||||
uint32_t video_writer_event_id = monitor->GetVideoWriterEventId();
|
||||
|
||||
if ( last_event_id != monitor->GetVideoWriterEventId() ) {
|
||||
Debug(2, "Have change of event. last_event(%d), our current (%d)", last_event_id, monitor->GetVideoWriterEventId() );
|
||||
if ( last_event_id != video_writer_event_id ) {
|
||||
Debug(2, "Have change of event. last_event(%d), our current (%d)", last_event_id, video_writer_event_id );
|
||||
|
||||
if ( videoStore ) {
|
||||
Info("Re-starting video storage module");
|
||||
|
|
|
@ -73,7 +73,12 @@ std::vector<std::string> split(const std::string &s, char delim) {
|
|||
return elems;
|
||||
}
|
||||
|
||||
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) {
|
||||
Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) :
|
||||
id( p_id ),
|
||||
shared_data(NULL),
|
||||
trigger_data(NULL),
|
||||
video_store_data(NULL)
|
||||
{
|
||||
strncpy( name, p_name, sizeof(name) );
|
||||
|
||||
#if ZM_MEM_MAPPED
|
||||
|
@ -468,9 +473,12 @@ Monitor::Monitor(
|
|||
videoRecording = ((GetOptVideoWriter() == H264PASSTHROUGH) && camera->SupportsNativeVideo());
|
||||
|
||||
if ( purpose == ANALYSIS ) {
|
||||
|
||||
while( shared_data->last_write_index == (unsigned int)image_buffer_count
|
||||
&& shared_data->last_write_time == 0) {
|
||||
Debug(2,"last_write_index(%d), last_write_time(%d)", shared_data->last_write_index, shared_data->last_write_time );
|
||||
while(
|
||||
( shared_data->last_write_index == (unsigned int)image_buffer_count )
|
||||
&&
|
||||
( shared_data->last_write_time == 0)
|
||||
) {
|
||||
Warning( "Waiting for capture daemon" );
|
||||
sleep( 1 );
|
||||
}
|
||||
|
@ -771,7 +779,14 @@ unsigned int Monitor::GetLastWriteIndex() const {
|
|||
return( shared_data->last_write_index!=(unsigned int)image_buffer_count?shared_data->last_write_index:-1 );
|
||||
}
|
||||
|
||||
unsigned int Monitor::GetLastEvent() const {
|
||||
uint32_t Monitor::GetLastEventId() const {
|
||||
Debug(2, "mem_ptr(%x), State(%d) last_read_index(%d) last_read_time(%d) last_event(%d)",
|
||||
mem_ptr,
|
||||
shared_data->state,
|
||||
shared_data->last_read_index,
|
||||
shared_data->last_read_time,
|
||||
shared_data->last_event
|
||||
);
|
||||
return( shared_data->last_event );
|
||||
}
|
||||
|
||||
|
|
|
@ -432,7 +432,6 @@ public:
|
|||
int GetOptSaveJPEGs() const { return( savejpegspref ); }
|
||||
VideoWriter GetOptVideoWriter() const { return( videowriter ); }
|
||||
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return( &encoderparamsvec ); }
|
||||
uint32_t GetLastEventId() const { return shared_data->last_event; }
|
||||
uint32_t GetVideoWriterEventId() const { return video_store_data->current_event; }
|
||||
void SetVideoWriterEventId( uint32_t p_event_id ) { video_store_data->current_event = p_event_id; }
|
||||
|
||||
|
@ -448,7 +447,7 @@ public:
|
|||
int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); }
|
||||
unsigned int GetLastReadIndex() const;
|
||||
unsigned int GetLastWriteIndex() const;
|
||||
unsigned int GetLastEvent() const;
|
||||
uint32_t GetLastEventId() const;
|
||||
double GetFPS() const;
|
||||
void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" );
|
||||
void ForceAlarmOff();
|
||||
|
|
|
@ -69,8 +69,8 @@ void StreamBase::updateFrameRate( double fps ) {
|
|||
while( effective_fps > maxfps ) {
|
||||
effective_fps /= 2.0;
|
||||
frame_mod *= 2;
|
||||
}
|
||||
Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod );
|
||||
}
|
||||
}
|
||||
|
||||
bool StreamBase::checkCommandQueue() {
|
||||
|
|
|
@ -195,6 +195,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
|||
|
||||
converted_in_samples = NULL;
|
||||
audio_out_codec = NULL;
|
||||
audio_in_codec = NULL;
|
||||
audio_in_ctx = NULL;
|
||||
audio_out_stream = NULL;
|
||||
in_frame = NULL;
|
||||
|
@ -411,12 +412,34 @@ VideoStore::~VideoStore() {
|
|||
// Just do a file open/close/writeheader/etc.
|
||||
// What if we were only doing audio recording?
|
||||
if (video_out_stream) {
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// We allocate and copy in newer ffmpeg, so need to free it
|
||||
avcodec_free_context(&video_in_ctx);
|
||||
#endif
|
||||
video_in_ctx=NULL;
|
||||
|
||||
avcodec_close(video_out_ctx);
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
avcodec_free_context(&video_out_ctx);
|
||||
#endif
|
||||
video_out_ctx = NULL;
|
||||
Debug(4, "Success freeing video_out_ctx");
|
||||
}
|
||||
if (audio_out_stream) {
|
||||
if ( audio_out_stream ) {
|
||||
if ( audio_in_codec ) {
|
||||
avcodec_close(audio_in_ctx);
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// We allocate and copy in newer ffmpeg, so need to free it
|
||||
avcodec_free_context(&audio_in_ctx);
|
||||
#endif
|
||||
audio_in_ctx = NULL;
|
||||
audio_in_codec = NULL;
|
||||
} // end if audio_in_codec
|
||||
|
||||
avcodec_close(audio_out_ctx);
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
avcodec_free_context(&audio_out_ctx);
|
||||
#endif
|
||||
audio_out_ctx = NULL;
|
||||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
if (resample_ctx) {
|
||||
|
@ -459,10 +482,10 @@ bool VideoStore::setup_resampler() {
|
|||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// Newer ffmpeg wants to keep everything separate... so have to lookup our own
|
||||
// decoder, can't reuse the one from the camera.
|
||||
AVCodec *audio_in_codec =
|
||||
audio_in_codec =
|
||||
avcodec_find_decoder(audio_in_stream->codecpar->codec_id);
|
||||
#else
|
||||
AVCodec *audio_in_codec =
|
||||
audio_in_codec =
|
||||
avcodec_find_decoder(audio_in_ctx->codec_id);
|
||||
#endif
|
||||
ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL);
|
||||
|
@ -783,7 +806,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
|
|||
}
|
||||
|
||||
opkt.flags = ipkt->flags;
|
||||
int keyframe = opkt.flags & AV_PKT_FLAG_KEY;
|
||||
opkt.pos = -1;
|
||||
|
||||
opkt.data = ipkt->data;
|
||||
|
@ -797,7 +819,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
|
|||
Debug(1,
|
||||
"writing video packet keyframe(%d) pts(%d) dts(%d) duration(%d) "
|
||||
"ipkt.duration(%d)",
|
||||
keyframe, opkt.pts, opkt.dts, duration, ipkt->duration);
|
||||
opkt.flags & AV_PKT_FLAG_KEY, opkt.pts, opkt.dts, duration, ipkt->duration);
|
||||
if ((opkt.data == NULL) || (opkt.size < 1)) {
|
||||
Warning("%s:%d: Mangled AVPacket: discarding frame", __FILE__, __LINE__);
|
||||
dumpPacket(ipkt);
|
||||
|
@ -870,6 +892,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
|
|||
* If we are at the end of the file, pass an empty packet to the decoder
|
||||
* to flush it.
|
||||
*/
|
||||
int data_present;
|
||||
if ((ret = avcodec_decode_audio4(audio_in_ctx, in_frame,
|
||||
&data_present, ipkt)) < 0) {
|
||||
Error("Could not decode frame (error '%s')\n",
|
||||
|
|
|
@ -16,7 +16,6 @@ extern "C" {
|
|||
|
||||
class VideoStore {
|
||||
private:
|
||||
unsigned int packets_written;
|
||||
|
||||
AVOutputFormat *out_format;
|
||||
AVFormatContext *oc;
|
||||
|
@ -34,13 +33,13 @@ private:
|
|||
AVFrame *out_frame;
|
||||
|
||||
AVCodecContext *video_in_ctx;
|
||||
AVCodec *audio_in_codec;
|
||||
AVCodecContext *audio_in_ctx;
|
||||
int ret;
|
||||
|
||||
// The following are used when encoding the audio stream to AAC
|
||||
AVCodec *audio_out_codec;
|
||||
AVCodecContext *audio_out_ctx;
|
||||
int data_present;
|
||||
AVAudioFifo *fifo;
|
||||
int out_frame_size;
|
||||
#ifdef HAVE_LIBAVRESAMPLE
|
||||
|
|
|
@ -514,10 +514,10 @@ int main( int argc, char *argv[] ) {
|
|||
}
|
||||
if ( function & ZMU_EVENT ) {
|
||||
if ( verbose )
|
||||
printf( "Last event id: %d\n", monitor->GetLastEvent() );
|
||||
printf( "Last event id: %d\n", monitor->GetLastEventId() );
|
||||
else {
|
||||
if ( have_output ) printf( "%c", separator );
|
||||
printf( "%d", monitor->GetLastEvent() );
|
||||
printf( "%d", monitor->GetLastEventId() );
|
||||
have_output = true;
|
||||
}
|
||||
}
|
||||
|
@ -712,7 +712,7 @@ int main( int argc, char *argv[] ) {
|
|||
tv.tv_sec, tv.tv_usec/10000,
|
||||
monitor->GetLastReadIndex(),
|
||||
monitor->GetLastWriteIndex(),
|
||||
monitor->GetLastEvent(),
|
||||
monitor->GetLastEventId(),
|
||||
monitor->GetFPS()
|
||||
);
|
||||
delete monitor;
|
||||
|
|
|
@ -76,6 +76,19 @@ if ( canView( 'Events' ) ) {
|
|||
ajaxError( 'Export Failed' );
|
||||
break;
|
||||
}
|
||||
case 'download' :
|
||||
{
|
||||
require_once( ZM_SKIN_PATH.'/includes/export_functions.php' );
|
||||
$exportVideo = 1;
|
||||
$exportFormat = $_REQUEST['exportFormat'];
|
||||
$exportStructure = 'flat';
|
||||
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
|
||||
if ( $exportFile = exportEvents( $exportIds, false, false, false, $exportVideo, false, $exportFormat, $exportStructure ) )
|
||||
ajaxResponse( array( 'exportFile'=>$exportFile ) );
|
||||
else
|
||||
ajaxError( 'Export Failed' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<?php
|
||||
if ($_REQUEST['entity'] == "navBar") {
|
||||
ajaxResponse(getNavBarHtml('reload'));
|
||||
return;
|
||||
}
|
||||
|
||||
$statusData = array(
|
||||
'system' => array(
|
||||
|
|
|
@ -116,7 +116,9 @@ switch ( $data['type'] ) {
|
|||
case MSG_DATA_WATCH :
|
||||
{
|
||||
$data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg );
|
||||
Logger::Debug("FPS: " . $data['fps'] );
|
||||
$data['fps'] = round( $data['fps'], 2 );
|
||||
Logger::Debug("FPS: " . $data['fps'] );
|
||||
$data['rate'] /= RATE_BASE;
|
||||
$data['delay'] = round( $data['delay'], 2 );
|
||||
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
|
||||
|
|
|
@ -14,16 +14,14 @@ class EventsController extends AppController {
|
|||
*/
|
||||
public $components = array('RequestHandler', 'Scaler', 'Image', 'Paginator');
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
$canView = $this->Session->Read('eventPermission');
|
||||
if ($canView =='None')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
$canView = $this->Session->Read('eventPermission');
|
||||
if ($canView =='None') {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* index method
|
||||
|
@ -48,14 +46,7 @@ public function beforeFilter() {
|
|||
} else {
|
||||
$conditions = array();
|
||||
}
|
||||
|
||||
// How many events to return
|
||||
$this->loadModel('Config');
|
||||
$limit = $this->Config->find('list', array(
|
||||
'conditions' => array('Name' => 'ZM_WEB_EVENTS_PER_PAGE'),
|
||||
'fields' => array('Name', 'Value')
|
||||
));
|
||||
$this->Paginator->settings = array(
|
||||
$settings = array(
|
||||
// https://github.com/ZoneMinder/ZoneMinder/issues/995
|
||||
// 'limit' => $limit['ZM_WEB_EVENTS_PER_PAGE'],
|
||||
// 25 events per page which is what the above
|
||||
|
@ -65,11 +56,31 @@ public function beforeFilter() {
|
|||
// make a nice ZM_API_ITEMS_PER_PAGE for all pagination
|
||||
// API
|
||||
|
||||
'limit' => '100',
|
||||
'limit' => '100',
|
||||
'order' => array('StartTime', 'MaxScore'),
|
||||
'paramType' => 'querystring',
|
||||
'conditions' => array (array($conditions, $mon_options))
|
||||
);
|
||||
);
|
||||
//if ( $this->request->params['GroupId'] ) {
|
||||
$settings['joins'] = array(
|
||||
array(
|
||||
'table' => 'Groups_Monitors',
|
||||
'type' => 'inner',
|
||||
'conditions' => array(
|
||||
'Groups_Monitors.MonitorId = Event.MonitorId'
|
||||
),
|
||||
),
|
||||
);
|
||||
$settings['contain'] = array('Group');
|
||||
//}
|
||||
$settings['conditions'] = array($conditions, $mon_options);
|
||||
|
||||
// How many events to return
|
||||
$this->loadModel('Config');
|
||||
$limit = $this->Config->find('list', array(
|
||||
'conditions' => array('Name' => 'ZM_WEB_EVENTS_PER_PAGE'),
|
||||
'fields' => array('Name', 'Value')
|
||||
));
|
||||
$this->Paginator->settings = $settings;
|
||||
$events = $this->Paginator->paginate('Event');
|
||||
|
||||
// For each event, get its thumbnail data (path, width, height)
|
||||
|
@ -89,282 +100,281 @@ public function beforeFilter() {
|
|||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function view($id = null)
|
||||
{
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
|
||||
));
|
||||
public function view($id = null) {
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
|
||||
));
|
||||
|
||||
$this->Event->recursive = 1;
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
$this->Event->recursive = 1;
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
|
||||
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
if (!empty($allowedMonitors))
|
||||
{
|
||||
$mon_options = array('Event.MonitorId' => $allowedMonitors);
|
||||
}
|
||||
else
|
||||
{
|
||||
$mon_options='';
|
||||
}
|
||||
|
||||
$options = array('conditions' => array(array('Event.' . $this->Event->primaryKey => $id), $mon_options));
|
||||
$event = $this->Event->find('first', $options);
|
||||
if (!empty($allowedMonitors))
|
||||
{
|
||||
$mon_options = array('Event.MonitorId' => $allowedMonitors);
|
||||
}
|
||||
else
|
||||
{
|
||||
$mon_options='';
|
||||
}
|
||||
|
||||
$path = $configs['ZM_DIR_EVENTS'].'/'.$this->Image->getEventPath($event).'/';
|
||||
$event['Event']['BasePath'] = $path;
|
||||
$options = array('conditions' => array(array('Event.' . $this->Event->primaryKey => $id), $mon_options));
|
||||
$event = $this->Event->find('first', $options);
|
||||
|
||||
# Get the previous and next events for any monitor
|
||||
$this->Event->id = $id;
|
||||
$event_neighbors = $this->Event->find('neighbors');
|
||||
$event['Event']['Next'] = $event_neighbors['next']['Event']['Id'];
|
||||
$event['Event']['Prev'] = $event_neighbors['prev']['Event']['Id'];
|
||||
$path = $configs['ZM_DIR_EVENTS'].'/'.$this->Image->getEventPath($event).'/';
|
||||
$event['Event']['BasePath'] = $path;
|
||||
|
||||
# Also get the previous and next events for the same monitor
|
||||
$event_monitor_neighbors = $this->Event->find('neighbors', array(
|
||||
'conditions'=>array('Event.MonitorId'=>$event['Event']['MonitorId'])
|
||||
));
|
||||
$event['Event']['NextOfMonitor'] = $event_monitor_neighbors['next']['Event']['Id'];
|
||||
$event['Event']['PrevOfMonitor'] = $event_monitor_neighbors['prev']['Event']['Id'];
|
||||
# Get the previous and next events for any monitor
|
||||
$this->Event->id = $id;
|
||||
$event_neighbors = $this->Event->find('neighbors');
|
||||
$event['Event']['Next'] = $event_neighbors['next']['Event']['Id'];
|
||||
$event['Event']['Prev'] = $event_neighbors['prev']['Event']['Id'];
|
||||
|
||||
$this->set(array(
|
||||
'event' => $event,
|
||||
'_serialize' => array('event')
|
||||
));
|
||||
}
|
||||
# Also get the previous and next events for the same monitor
|
||||
$event_monitor_neighbors = $this->Event->find('neighbors', array(
|
||||
'conditions'=>array('Event.MonitorId'=>$event['Event']['MonitorId'])
|
||||
));
|
||||
$event['Event']['NextOfMonitor'] = $event_monitor_neighbors['next']['Event']['Id'];
|
||||
$event['Event']['PrevOfMonitor'] = $event_monitor_neighbors['prev']['Event']['Id'];
|
||||
|
||||
$this->set(array(
|
||||
'event' => $event,
|
||||
'_serialize' => array('event')
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* add method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
/**
|
||||
* add method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
|
||||
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
$this->Event->create();
|
||||
if ($this->Event->save($this->request->data)) {
|
||||
return $this->flash(__('The event has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
$monitors = $this->Event->Monitor->find('list');
|
||||
$this->set(compact('monitors'));
|
||||
}
|
||||
if ($this->request->is('post')) {
|
||||
$this->Event->create();
|
||||
if ($this->Event->save($this->request->data)) {
|
||||
return $this->flash(__('The event has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
$monitors = $this->Event->Monitor->find('list');
|
||||
$this->set(compact('monitors'));
|
||||
}
|
||||
|
||||
/**
|
||||
* edit method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id = null) {
|
||||
/**
|
||||
* edit method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id = null) {
|
||||
|
||||
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->Event->id = $id;
|
||||
$this->Event->id = $id;
|
||||
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
|
||||
if ($this->Event->save($this->request->data)) {
|
||||
$message = 'Saved';
|
||||
} else {
|
||||
$message = 'Error';
|
||||
}
|
||||
if ($this->Event->save($this->request->data)) {
|
||||
$message = 'Saved';
|
||||
} else {
|
||||
$message = 'Error';
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
'_serialize' => array('message')
|
||||
));
|
||||
}
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
'_serialize' => array('message')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* delete method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
$this->Event->id = $id;
|
||||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
if ($this->Event->delete()) {
|
||||
//$this->loadModel('Frame');
|
||||
//$this->Event->Frame->delete();
|
||||
return $this->flash(__('The event has been deleted.'), array('action' => 'index'));
|
||||
} else {
|
||||
return $this->flash(__('The event could not be deleted. Please, try again.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* delete method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||
return;
|
||||
}
|
||||
$this->Event->id = $id;
|
||||
if (!$this->Event->exists()) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
if ($this->Event->delete()) {
|
||||
//$this->loadModel('Frame');
|
||||
//$this->Event->Frame->delete();
|
||||
return $this->flash(__('The event has been deleted.'), array('action' => 'index'));
|
||||
} else {
|
||||
return $this->flash(__('The event could not be deleted. Please, try again.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
|
||||
public function search() {
|
||||
$this->Event->recursive = -1;
|
||||
$conditions = array();
|
||||
public function search() {
|
||||
$this->Event->recursive = -1;
|
||||
$conditions = array();
|
||||
|
||||
foreach ($this->params['named'] as $param_name => $value) {
|
||||
// Transform params into mysql
|
||||
if (preg_match("/interval/i", $value, $matches)) {
|
||||
$condition = array("$param_name >= (date_sub(now(), $value))");
|
||||
} else {
|
||||
$condition = array($param_name => $value);
|
||||
}
|
||||
array_push($conditions, $condition);
|
||||
}
|
||||
foreach ($this->params['named'] as $param_name => $value) {
|
||||
// Transform params into mysql
|
||||
if (preg_match("/interval/i", $value, $matches)) {
|
||||
$condition = array("$param_name >= (date_sub(now(), $value))");
|
||||
} else {
|
||||
$condition = array($param_name => $value);
|
||||
}
|
||||
array_push($conditions, $condition);
|
||||
}
|
||||
|
||||
$results = $this->Event->find('all', array(
|
||||
'conditions' => $conditions
|
||||
));
|
||||
$results = $this->Event->find('all', array(
|
||||
'conditions' => $conditions
|
||||
));
|
||||
|
||||
$this->set(array(
|
||||
'results' => $results,
|
||||
'_serialize' => array('results')
|
||||
));
|
||||
$this->set(array(
|
||||
'results' => $results,
|
||||
'_serialize' => array('results')
|
||||
));
|
||||
|
||||
|
||||
}
|
||||
|
||||
// format expected:
|
||||
// you can changed AlarmFrames to any other named params
|
||||
// consoleEvents/1 hour/AlarmFrames >=: 1/AlarmFrames <=: 20.json
|
||||
}
|
||||
|
||||
public function consoleEvents($interval = null) {
|
||||
$this->Event->recursive = -1;
|
||||
$results = array();
|
||||
// format expected:
|
||||
// you can changed AlarmFrames to any other named params
|
||||
// consoleEvents/1 hour/AlarmFrames >=: 1/AlarmFrames <=: 20.json
|
||||
|
||||
$moreconditions ="";
|
||||
foreach ($this->request->params['named'] as $name => $param) {
|
||||
$moreconditions = $moreconditions . " AND ".$name.$param;
|
||||
}
|
||||
|
||||
$query = $this->Event->query("select MonitorId, COUNT(*) AS Count from Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;");
|
||||
public function consoleEvents($interval = null) {
|
||||
$this->Event->recursive = -1;
|
||||
$results = array();
|
||||
|
||||
foreach ($query as $result) {
|
||||
$results[$result['Events']['MonitorId']] = $result[0]['Count'];
|
||||
}
|
||||
$moreconditions ="";
|
||||
foreach ($this->request->params['named'] as $name => $param) {
|
||||
$moreconditions = $moreconditions . " AND ".$name.$param;
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'results' => $results,
|
||||
'_serialize' => array('results')
|
||||
));
|
||||
}
|
||||
$query = $this->Event->query("select MonitorId, COUNT(*) AS Count from Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;");
|
||||
|
||||
// Create a thumbnail and return the thumbnail's data for a given event id.
|
||||
public function createThumbnail($id = null) {
|
||||
$this->Event->recursive = -1;
|
||||
foreach ($query as $result) {
|
||||
$results[$result['Events']['MonitorId']] = $result[0]['Count'];
|
||||
}
|
||||
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
$this->set(array(
|
||||
'results' => $results,
|
||||
'_serialize' => array('results')
|
||||
));
|
||||
}
|
||||
|
||||
$event = $this->Event->find('first', array(
|
||||
'conditions' => array('Id' => $id)
|
||||
));
|
||||
// Create a thumbnail and return the thumbnail's data for a given event id.
|
||||
public function createThumbnail($id = null) {
|
||||
$this->Event->recursive = -1;
|
||||
|
||||
// Find the max Frame for this Event. Error out otherwise.
|
||||
$this->loadModel('Frame');
|
||||
if (! $frame = $this->Frame->find('first', array(
|
||||
'conditions' => array(
|
||||
'EventId' => $event['Event']['Id'],
|
||||
'Score' => $event['Event']['MaxScore']
|
||||
)
|
||||
))) {
|
||||
throw new NotFoundException(__("Can not find Frame for Event " . $event['Event']['Id']));
|
||||
}
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
|
||||
$this->loadModel('Config');
|
||||
$event = $this->Event->find('first', array(
|
||||
'conditions' => array('Id' => $id)
|
||||
));
|
||||
|
||||
// Get the config options required for reScale and getImageSrc
|
||||
// The $bw, $thumbs and unset() code is a workaround / temporary
|
||||
// until I have a better way of handing per-bandwidth config options
|
||||
$bw = (isset($_COOKIE['zmBandwidth']) ? strtoupper(substr($_COOKIE['zmBandwidth'], 0, 1)) : 'L');
|
||||
$thumbs = "ZM_WEB_${bw}_SCALE_THUMBS";
|
||||
// Find the max Frame for this Event. Error out otherwise.
|
||||
$this->loadModel('Frame');
|
||||
if (! $frame = $this->Frame->find('first', array(
|
||||
'conditions' => array(
|
||||
'EventId' => $event['Event']['Id'],
|
||||
'Score' => $event['Event']['MaxScore']
|
||||
)
|
||||
))) {
|
||||
throw new NotFoundException(__("Can not find Frame for Event " . $event['Event']['Id']));
|
||||
}
|
||||
|
||||
$config = $this->Config->find('list', array(
|
||||
'conditions' => array('OR' => array(
|
||||
'Name' => array('ZM_WEB_LIST_THUMB_WIDTH',
|
||||
'ZM_WEB_LIST_THUMB_HEIGHT',
|
||||
'ZM_EVENT_IMAGE_DIGITS',
|
||||
'ZM_DIR_IMAGES',
|
||||
"$thumbs",
|
||||
'ZM_DIR_EVENTS'
|
||||
)
|
||||
)),
|
||||
'fields' => array('Name', 'Value')
|
||||
));
|
||||
$config['ZM_WEB_SCALE_THUMBS'] = $config[$thumbs];
|
||||
unset($config[$thumbs]);
|
||||
$this->loadModel('Config');
|
||||
|
||||
// reScale based on either the width, or the hight, of the event.
|
||||
if ( $config['ZM_WEB_LIST_THUMB_WIDTH'] ) {
|
||||
$thumbWidth = $config['ZM_WEB_LIST_THUMB_WIDTH'];
|
||||
$scale = (100 * $thumbWidth) / $event['Event']['Width'];
|
||||
$thumbHeight = $this->Scaler->reScale( $event['Event']['Height'], $scale );
|
||||
}
|
||||
elseif ( $config['ZM_WEB_LIST_THUMB_HEIGHT'] ) {
|
||||
$thumbHeight = $config['ZM_WEB_LIST_THUMB_HEIGHT'];
|
||||
$scale = (100*$thumbHeight)/$event['Event']['Height'];
|
||||
$thumbWidth = $this->Scaler->reScale( $event['Event']['Width'], $scale );
|
||||
}
|
||||
else {
|
||||
throw new NotFoundException(__('No thumbnail width or height specified, please check in Options->Web'));
|
||||
}
|
||||
// Get the config options required for reScale and getImageSrc
|
||||
// The $bw, $thumbs and unset() code is a workaround / temporary
|
||||
// until I have a better way of handing per-bandwidth config options
|
||||
$bw = (isset($_COOKIE['zmBandwidth']) ? strtoupper(substr($_COOKIE['zmBandwidth'], 0, 1)) : 'L');
|
||||
$thumbs = "ZM_WEB_${bw}_SCALE_THUMBS";
|
||||
|
||||
$imageData = $this->Image->getImageSrc( $event, $frame, $scale, $config );
|
||||
$thumbData['Path'] = $imageData['thumbPath'];
|
||||
$thumbData['Width'] = (int)$thumbWidth;
|
||||
$thumbData['Height'] = (int)$thumbHeight;
|
||||
|
||||
return( $thumbData );
|
||||
$config = $this->Config->find('list', array(
|
||||
'conditions' => array('OR' => array(
|
||||
'Name' => array('ZM_WEB_LIST_THUMB_WIDTH',
|
||||
'ZM_WEB_LIST_THUMB_HEIGHT',
|
||||
'ZM_EVENT_IMAGE_DIGITS',
|
||||
'ZM_DIR_IMAGES',
|
||||
"$thumbs",
|
||||
'ZM_DIR_EVENTS'
|
||||
)
|
||||
)),
|
||||
'fields' => array('Name', 'Value')
|
||||
));
|
||||
$config['ZM_WEB_SCALE_THUMBS'] = $config[$thumbs];
|
||||
unset($config[$thumbs]);
|
||||
|
||||
}
|
||||
// reScale based on either the width, or the hight, of the event.
|
||||
if ( $config['ZM_WEB_LIST_THUMB_WIDTH'] ) {
|
||||
$thumbWidth = $config['ZM_WEB_LIST_THUMB_WIDTH'];
|
||||
$scale = (100 * $thumbWidth) / $event['Event']['Width'];
|
||||
$thumbHeight = $this->Scaler->reScale( $event['Event']['Height'], $scale );
|
||||
}
|
||||
elseif ( $config['ZM_WEB_LIST_THUMB_HEIGHT'] ) {
|
||||
$thumbHeight = $config['ZM_WEB_LIST_THUMB_HEIGHT'];
|
||||
$scale = (100*$thumbHeight)/$event['Event']['Height'];
|
||||
$thumbWidth = $this->Scaler->reScale( $event['Event']['Width'], $scale );
|
||||
}
|
||||
else {
|
||||
throw new NotFoundException(__('No thumbnail width or height specified, please check in Options->Web'));
|
||||
}
|
||||
|
||||
public function archive($id = null) {
|
||||
$this->Event->recursive = -1;
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
$imageData = $this->Image->getImageSrc( $event, $frame, $scale, $config );
|
||||
$thumbData['Path'] = $imageData['thumbPath'];
|
||||
$thumbData['Width'] = (int)$thumbWidth;
|
||||
$thumbData['Height'] = (int)$thumbHeight;
|
||||
|
||||
// Get the current value of Archive
|
||||
$archived = $this->Event->find('first', array(
|
||||
'fields' => array('Event.Archived'),
|
||||
'conditions' => array('Event.Id' => $id)
|
||||
));
|
||||
// If 0, 1, if 1, 0
|
||||
$archiveVal = (($archived['Event']['Archived'] == 0) ? 1 : 0);
|
||||
return( $thumbData );
|
||||
|
||||
// Save the new value
|
||||
$this->Event->id = $id;
|
||||
$this->Event->saveField('Archived', $archiveVal);
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'archived' => $archiveVal,
|
||||
'_serialize' => array('archived')
|
||||
));
|
||||
}
|
||||
public function archive($id = null) {
|
||||
$this->Event->recursive = -1;
|
||||
if (!$this->Event->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid event'));
|
||||
}
|
||||
|
||||
// Get the current value of Archive
|
||||
$archived = $this->Event->find('first', array(
|
||||
'fields' => array('Event.Archived'),
|
||||
'conditions' => array('Event.Id' => $id)
|
||||
));
|
||||
// If 0, 1, if 1, 0
|
||||
$archiveVal = (($archived['Event']['Archived'] == 0) ? 1 : 0);
|
||||
|
||||
// Save the new value
|
||||
$this->Event->id = $id;
|
||||
$this->Event->saveField('Archived', $archiveVal);
|
||||
|
||||
$this->set(array(
|
||||
'archived' => $archiveVal,
|
||||
'_serialize' => array('archived')
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
/**
|
||||
* Groups Controller
|
||||
*
|
||||
* @property Group $Group
|
||||
*/
|
||||
class GroupsController extends AppController {
|
||||
|
||||
/**
|
||||
* Components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = array('RequestHandler');
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function index() {
|
||||
$this->Group->recursive = -1;
|
||||
$groups = $this->Group->find('all');
|
||||
$this->set(array(
|
||||
'groups' => $groups,
|
||||
'_serialize' => array('groups')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* view method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function view($id = null) {
|
||||
$this->Group->recursive = -1;
|
||||
if (!$this->Group->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid group'));
|
||||
}
|
||||
$options = array('conditions' => array('Group.' . $this->Group->primaryKey => $id));
|
||||
$group = $this->Group->find('first', $options);
|
||||
$this->set(array(
|
||||
'group' => $group,
|
||||
'_serialize' => array('group')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* add method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
if ($this->request->is('post')) {
|
||||
$this->Group->create();
|
||||
if ($this->Group->save($this->request->data)) {
|
||||
return $this->flash(__('The group has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
}
|
||||
$monitors = $this->Group->Monitor->find('list');
|
||||
$this->set(compact('monitors'));
|
||||
}
|
||||
|
||||
/**
|
||||
* edit method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function edit($id = null) {
|
||||
if (!$this->Group->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid group'));
|
||||
}
|
||||
if ($this->request->is(array('post', 'put'))) {
|
||||
if ($this->Group->save($this->request->data)) {
|
||||
return $this->flash(__('The group has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
} else {
|
||||
$options = array('conditions' => array('Group.' . $this->Group->primaryKey => $id));
|
||||
$this->request->data = $this->Group->find('first', $options);
|
||||
}
|
||||
$monitors = $this->Group->Monitor->find('list');
|
||||
$this->set(compact('monitors'));
|
||||
}
|
||||
|
||||
/**
|
||||
* delete method
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id = null) {
|
||||
$this->Group->id = $id;
|
||||
if (!$this->Group->exists()) {
|
||||
throw new NotFoundException(__('Invalid group'));
|
||||
}
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
if ($this->Group->delete()) {
|
||||
return $this->flash(__('The group has been deleted.'), array('action' => 'index'));
|
||||
} else {
|
||||
return $this->flash(__('The group could not be deleted. Please, try again.'), array('action' => 'index'));
|
||||
}
|
||||
}}
|
|
@ -8,7 +8,6 @@ App::uses('AppController', 'Controller');
|
|||
*/
|
||||
class MonitorsController extends AppController {
|
||||
|
||||
|
||||
/**
|
||||
* Components
|
||||
*
|
||||
|
@ -16,18 +15,14 @@ class MonitorsController extends AppController {
|
|||
*/
|
||||
public $components = array('Paginator', 'RequestHandler');
|
||||
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
$canView = $this->Session->Read('monitorPermission');
|
||||
if ($canView =='None')
|
||||
{
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
$canView = $this->Session->Read('monitorPermission');
|
||||
if ($canView =='None') {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* index method
|
||||
|
@ -36,7 +31,7 @@ public function beforeFilter() {
|
|||
*/
|
||||
public function index() {
|
||||
$this->Monitor->recursive = 0;
|
||||
|
||||
|
||||
if ($this->request->params['named']) {
|
||||
$this->FilterComponent = $this->Components->load('Filter');
|
||||
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
||||
|
@ -48,7 +43,28 @@ public function beforeFilter() {
|
|||
if (!empty($allowedMonitors)) {
|
||||
$conditions['Monitor.Id' ] = $allowedMonitors;
|
||||
}
|
||||
$monitors = $this->Monitor->find('all',array('conditions'=>$conditions));
|
||||
$find_array = array('conditions'=>$conditions,'contain'=>array('Group'));
|
||||
|
||||
//if ( $this->request->params['GroupId'] ) {
|
||||
$find_array['joins'] = array(
|
||||
array(
|
||||
'table' => 'Groups_Monitors',
|
||||
'type' => 'inner',
|
||||
'conditions' => array(
|
||||
'Groups_Monitors.MonitorId = Monitor.Id'
|
||||
),
|
||||
),
|
||||
//array(
|
||||
//'table' => 'Groups',
|
||||
//'type' => 'inner',
|
||||
//'conditions' => array(
|
||||
//'Groups.Id = Groups_Monitors.GroupId',
|
||||
//'Groups.Id' => $this->request->params['GroupId'],
|
||||
//),
|
||||
//)
|
||||
);
|
||||
//}
|
||||
$monitors = $this->Monitor->find('all',$find_array);
|
||||
$this->set(array(
|
||||
'monitors' => $monitors,
|
||||
'_serialize' => array('monitors')
|
||||
|
|
|
@ -68,4 +68,28 @@ class Event extends AppModel {
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* * * hasMany associations
|
||||
* * *
|
||||
* * * @var array
|
||||
* * */
|
||||
public $hasAndBelongsToMany = array(
|
||||
'Group' => array(
|
||||
'className' => 'Group',
|
||||
'joinTable' => 'Groups_Monitors',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'associationForeignKey' => 'GroupId',
|
||||
'unique' => true,
|
||||
'dependent' => false,
|
||||
'conditions' => 'Groups_Monitors.MonitorId=Event.MonitorId',
|
||||
'fields' => '',
|
||||
'order' => '',
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
'finderQuery' => '',
|
||||
'counterQuery' => ''
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
/**
|
||||
* Group Model
|
||||
*
|
||||
* @property Event $Event
|
||||
*/
|
||||
class Group extends AppModel {
|
||||
|
||||
/**
|
||||
* Use table
|
||||
*
|
||||
* @var mixed False or table name
|
||||
*/
|
||||
public $useTable = 'Groups';
|
||||
|
||||
/**
|
||||
* Primary key field
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $primaryKey = 'Id';
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $validate = array(
|
||||
'Name' => array(
|
||||
'notEmpty' => array(
|
||||
'rule' => array('notEmpty'),
|
||||
//'message' => 'Your custom message here',
|
||||
//'allowEmpty' => false,
|
||||
//'required' => false,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public $recursive = -1;
|
||||
//The Associations below have been created with all possible keys, those that are not needed can be removed
|
||||
|
||||
/**
|
||||
* hasMany associations
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $hasMany = array(
|
||||
'Monitor' => array(
|
||||
'className' => 'Monitor',
|
||||
'joinTable' => 'Groups_Monitors',
|
||||
'foreignKey' => 'GroupId',
|
||||
'associationForeignKey' => 'MonitorId',
|
||||
'unique'=>true,
|
||||
'dependent' => false,
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => '',
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
'finderQuery' => '',
|
||||
'counterQuery' => ''
|
||||
),
|
||||
);
|
||||
}
|
|
@ -85,4 +85,28 @@ class Monitor extends AppModel {
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* * hasMany associations
|
||||
* *
|
||||
* * @var array
|
||||
* */
|
||||
public $hasAndBelongsToMany = array(
|
||||
'Group' => array(
|
||||
'className' => 'Group',
|
||||
'joinTable' => 'Groups_Monitors',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'associationForeignKey' => 'GroupId',
|
||||
'unique' => true,
|
||||
'dependent' => false,
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => '',
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
'finderQuery' => '',
|
||||
'counterQuery' => ''
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $monitors));
|
||||
$xml = Xml::fromArray(array('response' => $servers));
|
||||
echo $xml->asXML();
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $monitor));
|
||||
$xml = Xml::fromArray(array('response' => $server));
|
||||
echo $xml->asXML();
|
||||
|
|
|
@ -12,6 +12,8 @@ public $defaults = array(
|
|||
'AutoArchive' => 0,
|
||||
'AutoVideo' => 0,
|
||||
'AutoMessage' => 0,
|
||||
'AutoMove' => 0,
|
||||
'AutoMoveTo' => 0,
|
||||
'UpdateDiskSpace' => 0,
|
||||
'Background' => 0,
|
||||
'Concurrent' => 0,
|
||||
|
|
|
@ -6,7 +6,6 @@ public $defaults = array(
|
|||
'Id' => null,
|
||||
'Name' => '',
|
||||
'ParentId' => null,
|
||||
'MonitorIds' => '',
|
||||
);
|
||||
|
||||
public function __construct( $IdOrRow=NULL ) {
|
||||
|
@ -88,7 +87,8 @@ public $defaults = array(
|
|||
|
||||
public function delete() {
|
||||
if ( array_key_exists( 'Id', $this ) ) {
|
||||
dbQuery( 'DELETE FROM Groups WHERE Id = ?', array($this->{'Id'}) );
|
||||
dbQuery( 'DELETE FROM Groups WHERE Id=?', array($this->{'Id'}) );
|
||||
dbQuery( 'DELETE FROM Groups_Monitors WHERE GroupId=?', array($this->{'Id'}) );
|
||||
if ( isset($_COOKIE['zmGroup']) ) {
|
||||
if ( $this->{'Id'} == $_COOKIE['zmGroup'] ) {
|
||||
unset( $_COOKIE['zmGroup'] );
|
||||
|
@ -128,6 +128,13 @@ public $defaults = array(
|
|||
return $this->{'depth'};
|
||||
} // end public function depth
|
||||
|
||||
public function MonitorIds( ) {
|
||||
if ( ! array_key_exists( 'MonitorIds', $this ) ) {
|
||||
$this->{'MonitorIds'} = dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($this->{'Id'}) );
|
||||
}
|
||||
return $this->{'MonitorIds'};
|
||||
}
|
||||
|
||||
public static function get_group_dropdowns() {
|
||||
# This will end up with the group_id of the deepest selection
|
||||
$group_id = 0;
|
||||
|
@ -164,19 +171,14 @@ public $defaults = array(
|
|||
return $group_id;
|
||||
} # end public static function get_group_dropdowns()
|
||||
|
||||
|
||||
public static function get_group_sql( $group_id ) {
|
||||
$groupSql = '';
|
||||
if ( $group_id ) {
|
||||
if ( $group = dbFetchOne( 'SELECT MonitorIds FROM Groups WHERE Id=?', NULL, array($group_id) ) ) {
|
||||
$groupIds = array();
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = explode( ',', $group['MonitorIds'] );
|
||||
$MonitorIds = dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($group_id) );
|
||||
|
||||
foreach ( dbFetchAll( 'SELECT MonitorIds FROM Groups WHERE ParentId = ?', NULL, array($group_id) ) as $group )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = array_merge( $groupIds, explode( ',', $group['MonitorIds'] ) );
|
||||
}
|
||||
$groupSql = " find_in_set( Id, '".implode( ',', $groupIds )."' )";
|
||||
$MonitorIds = array_merge( $MonitorIds, dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId IN (SELECT Id FROM Groups WHERE ParentId = ?)', 'MonitorId', array($group_id) ) );
|
||||
$groupSql = " find_in_set( Id, '".implode( ',', $MonitorIds )."' )";
|
||||
}
|
||||
return $groupSql;
|
||||
} # end public static function get_group_sql( $group_id )
|
||||
|
|
|
@ -142,7 +142,6 @@ if ( canView( 'Events' ) ) {
|
|||
|
||||
if ( isset( $_REQUEST['object'] ) and ( $_REQUEST['object'] == 'filter' ) ) {
|
||||
if ( $action == 'addterm' ) {
|
||||
Warning("Addterm");
|
||||
$_REQUEST['filter'] = addFilterTerm( $_REQUEST['filter'], $_REQUEST['line'] );
|
||||
} elseif ( $action == 'delterm' ) {
|
||||
$_REQUEST['filter'] = delFilterTerm( $_REQUEST['filter'], $_REQUEST['line'] );
|
||||
|
@ -173,6 +172,11 @@ Warning("Addterm");
|
|||
$sql .= ', AutoExecute = '. ( !empty($_REQUEST['filter']['AutoExecute']) ? 1 : 0);
|
||||
$sql .= ', AutoExecuteCmd = '.dbEscape($_REQUEST['filter']['AutoExecuteCmd']);
|
||||
$sql .= ', AutoDelete = '. ( !empty($_REQUEST['filter']['AutoDelete']) ? 1 : 0);
|
||||
if ( !empty($_REQUEST['filter']['AutoMove']) ? 1 : 0) {
|
||||
$sql .= ', AutoMove = 1, AutoMoveTo='. validInt($_REQUEST['filter']['AutoMoveTo']);
|
||||
} else {
|
||||
$sql .= ', AutoMove = 0';
|
||||
}
|
||||
$sql .= ', UpdateDiskSpace = '. ( !empty($_REQUEST['filter']['UpdateDiskSpace']) ? 1 : 0);
|
||||
$sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0);
|
||||
$sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 1 : 0);
|
||||
|
@ -542,7 +546,7 @@ if ( canEdit( 'Monitors' ) ) {
|
|||
$saferName = basename($_REQUEST['newMonitor']['Name']);
|
||||
symlink( $mid, ZM_DIR_EVENTS.'/'.$saferName );
|
||||
if ( isset($_COOKIE['zmGroup']) ) {
|
||||
dbQuery( "UPDATE Groups SET MonitorIds = concat(MonitorIds,',".$mid."') WHERE Id=?", array($_COOKIE['zmGroup']) );
|
||||
dbQuery( 'INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($_COOKIE['zmGroup'],$mid) );
|
||||
}
|
||||
} else {
|
||||
Error("Users with Monitors restrictions cannot create new monitors.");
|
||||
|
@ -662,12 +666,16 @@ if ( canEdit( 'Groups' ) ) {
|
|||
if ( $action == 'group' ) {
|
||||
$monitors = empty( $_POST['newGroup']['MonitorIds'] ) ? '' : implode(',', $_POST['newGroup']['MonitorIds']);
|
||||
if ( !empty($_POST['gid']) ) {
|
||||
dbQuery( 'UPDATE Groups SET Name=?, ParentId=?, MonitorIds=? WHERE Id=?',
|
||||
array($_POST['newGroup']['Name'], ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), $monitors, $_POST['gid']) );
|
||||
dbQuery( 'UPDATE Groups SET Name=?, ParentId=? WHERE Id=?',
|
||||
array($_POST['newGroup']['Name'], ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), $_POST['gid']) );
|
||||
dbQuery( 'DELETE FROM Groups_Monitors WHERE GroupId=?', array($_POST['gid']) );
|
||||
} else {
|
||||
dbQuery( 'INSERT INTO Groups SET Name=?, ParentId=?, MonitorIds=?',
|
||||
array( $_POST['newGroup']['Name'], ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), $monitors ) );
|
||||
}
|
||||
foreach ( $_POST['newGroup']['MonitorIds'] as $mid ) {
|
||||
dbQuery( 'INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($_POST['gid'], $mid) );
|
||||
}
|
||||
$view = 'none';
|
||||
$refreshParent = true;
|
||||
} else if ( $action == 'delete' ) {
|
||||
|
|
|
@ -137,19 +137,19 @@ require_once( 'database.php' );
|
|||
loadConfig();
|
||||
|
||||
$GLOBALS['defaultUser'] = array(
|
||||
"Username" => "admin",
|
||||
"Password" => "",
|
||||
"Language" => "",
|
||||
"Enabled" => 1,
|
||||
"Stream" => 'View',
|
||||
"Events" => 'Edit',
|
||||
"Control" => 'Edit',
|
||||
"Monitors" => 'Edit',
|
||||
"Groups" => 'Edit',
|
||||
"Devices" => 'Edit',
|
||||
"System" => 'Edit',
|
||||
"MaxBandwidth" => "",
|
||||
"MonitorIds" => false
|
||||
'Username' => "admin",
|
||||
'Password' => "",
|
||||
'Language' => "",
|
||||
'Enabled' => 1,
|
||||
'Stream' => 'View',
|
||||
'Events' => 'Edit',
|
||||
'Control' => 'Edit',
|
||||
'Monitors' => 'Edit',
|
||||
'Groups' => 'Edit',
|
||||
'Devices' => 'Edit',
|
||||
'System' => 'Edit',
|
||||
'MaxBandwidth' => '',
|
||||
'MonitorIds' => false
|
||||
);
|
||||
|
||||
function loadConfig( $defineConsts=true ) {
|
||||
|
@ -179,7 +179,7 @@ function loadConfig( $defineConsts=true ) {
|
|||
}
|
||||
|
||||
require_once( 'logger.php' );
|
||||
// For Human-readability, user ZM_SERVER in zm.conf, and convert it here to a ZM_SERVER_ID
|
||||
// For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID
|
||||
if ( ! defined('ZM_SERVER_ID') ) {
|
||||
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
|
||||
$server_id = dbFetchOne('SELECT Id FROM Servers WHERE Name=?', 'Id', array(ZM_SERVER_NAME));
|
||||
|
|
|
@ -189,21 +189,21 @@ function csrf_check($fatal = true) {
|
|||
$tokens = '';
|
||||
do {
|
||||
if (!isset($_POST[$name])) {
|
||||
Logger::Debug("POST[$name] is not set");
|
||||
#Logger::Debug("POST[$name] is not set");
|
||||
break;
|
||||
} else {
|
||||
Logger::Debug("POST[$name] is set as " . $_POST[$name] );
|
||||
#} else {
|
||||
#Logger::Debug("POST[$name] is set as " . $_POST[$name] );
|
||||
|
||||
}
|
||||
// we don't regenerate a token and check it because some token creation
|
||||
// schemes are volatile.
|
||||
$tokens = $_POST[$name];
|
||||
if (!csrf_check_tokens($tokens)) {
|
||||
Logger::Debug("Failed checking tokens");
|
||||
#Logger::Debug("Failed checking tokens");
|
||||
break;
|
||||
|
||||
} else {
|
||||
Logger::Debug("Token passed");
|
||||
#} else {
|
||||
#Logger::Debug("Token passed");
|
||||
}
|
||||
$ok = true;
|
||||
} while (false);
|
||||
|
@ -308,27 +308,27 @@ function csrf_check_tokens($tokens) {
|
|||
* Checks if a token is valid.
|
||||
*/
|
||||
function csrf_check_token($token) {
|
||||
Logger::Debug("Checking CSRF token $token");
|
||||
#Logger::Debug("Checking CSRF token $token");
|
||||
if (strpos($token, ':') === false) {
|
||||
Logger::Debug("Checking CSRF token $token bad because no :");
|
||||
#Logger::Debug("Checking CSRF token $token bad because no :");
|
||||
return false;
|
||||
}
|
||||
list($type, $value) = explode(':', $token, 2);
|
||||
if (strpos($value, ',') === false) {
|
||||
Logger::Debug("Checking CSRF token $token bad because no ,");
|
||||
#Logger::Debug("Checking CSRF token $token bad because no ,");
|
||||
return false;
|
||||
}
|
||||
list($x, $time) = explode(',', $token, 2);
|
||||
if ($GLOBALS['csrf']['expires']) {
|
||||
if (time() > $time + $GLOBALS['csrf']['expires']) {
|
||||
Logger::Debug("Checking CSRF token $token bad because expired");
|
||||
#Logger::Debug("Checking CSRF token $token bad because expired");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch ($type) {
|
||||
case 'sid':
|
||||
{
|
||||
Logger::Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) );
|
||||
#Logger::Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) );
|
||||
return $value === csrf_hash(session_id(), $time);
|
||||
}
|
||||
case 'cookie':
|
||||
|
@ -341,7 +341,7 @@ return false;
|
|||
Logger::Debug("Checking key: no key set" );
|
||||
return false;
|
||||
}
|
||||
Logger::Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) );
|
||||
#Logger::Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) );
|
||||
return $value === csrf_hash($GLOBALS['csrf']['key'], $time);
|
||||
// We could disable these 'weaker' checks if 'key' was set, but
|
||||
// that doesn't make me feel good then about the cookie-based
|
||||
|
|
|
@ -134,7 +134,7 @@ function dbQuery( $sql, $params=NULL ) {
|
|||
} else {
|
||||
$result = $dbConn->query( $sql );
|
||||
}
|
||||
if ( 0 ) {
|
||||
if ( defined('ZM_DB_DEBUG') ) {
|
||||
if ( $params )
|
||||
Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() );
|
||||
else
|
||||
|
|
|
@ -1872,7 +1872,10 @@ function monitorIdsToNames( $ids ) {
|
|||
}
|
||||
}
|
||||
$names = array();
|
||||
foreach ( preg_split( '/\s*,\s*/', $ids ) as $id ) {
|
||||
if ( ! is_array($ids) ) {
|
||||
$ids = preg_split( '/\s*,\s*/', $ids );
|
||||
}
|
||||
foreach ( $ids as $id ) {
|
||||
if ( visibleMonitor( $id ) ) {
|
||||
if ( isset($mITN_monitors[$id]) ) {
|
||||
$names[] = $mITN_monitors[$id]['Name'];
|
||||
|
|
|
@ -195,7 +195,7 @@ isset($action) || $action = NULL;
|
|||
|
||||
if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames') {
|
||||
require_once( 'includes/csrf/csrf-magic.php' );
|
||||
Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
||||
#Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
|
||||
csrf_check();
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,10 @@ function logReport( level, message, file, line )
|
|||
|
||||
if ( !debugReq )
|
||||
{
|
||||
debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+Browser.Platform.name;
|
||||
if ( Browser )
|
||||
debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+(Browser.Platform?Browser.Platform.name:'unknown');
|
||||
else
|
||||
debugParms = "view=request&request=log&task=create&browser[name]=unknown&browser[version]=unknown&browser[platform]=unknown";
|
||||
debugReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain' } );
|
||||
}
|
||||
var requestParms = debugParms;
|
||||
|
|
|
@ -322,6 +322,8 @@ $SLANG = array(
|
|||
'ExportDetails' => 'Export Event Details',
|
||||
'Exif' => 'Embed EXIF data into image',
|
||||
'Export' => 'Export',
|
||||
'DownloadVideo' => 'Download Video',
|
||||
'GenerateDownload' => 'Generate Download',
|
||||
'ExportFailed' => 'Export Failed',
|
||||
'ExportFormat' => 'Export File Format',
|
||||
'ExportFormatTar' => 'Tar',
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*
|
||||
* ZoneMinder Base Stylesheet, $Date$, $Revision$
|
||||
* Copyright (C) 2001-2008 Philip Coombes
|
||||
|
@ -346,9 +347,11 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
|
||||
#header {
|
||||
width: 100%;
|
||||
line-height: 24px;
|
||||
margin: 8px auto;
|
||||
margin: 0 auto 4px auto;
|
||||
line-height: 1;
|
||||
text-align: left;
|
||||
padding: 3px 0;
|
||||
border-bottom: 1px solid #555555;
|
||||
}
|
||||
|
||||
#header h2 {
|
||||
|
@ -378,7 +381,7 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
|
||||
#content {
|
||||
width: 96%;
|
||||
margin: 8px auto;
|
||||
margin: 0 auto 8px auto;
|
||||
line-height: 130%;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -12,109 +12,64 @@
|
|||
|
||||
.alarmCue {
|
||||
background-color: #222222;
|
||||
height: 1.5em;
|
||||
height: 1.25em;
|
||||
text-align: left;
|
||||
margin: 0 auto 0 auto;
|
||||
border-radius: 0 0 .3em .3em;
|
||||
}
|
||||
|
||||
.alarmCue span {
|
||||
background-color:red;
|
||||
height: 1.5em;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
span.noneCue {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#dataBar {
|
||||
width: 100%;
|
||||
margin: 2px auto;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-wrap:wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#dataBar #dataTable {
|
||||
#menuBar1 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
text-align: center;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
|
||||
#dataBar #dataTable td {
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
#menuBar1 #replayControl {
|
||||
margin: 0 4px 0 auto;
|
||||
}
|
||||
|
||||
#menuBar1 div {
|
||||
margin: auto 5px;
|
||||
}
|
||||
|
||||
#nameControl input[type="button"]{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#eventVideo {
|
||||
display: inline-block;
|
||||
postion: relative;
|
||||
}
|
||||
|
||||
#menuBar1 {
|
||||
width: 100%;
|
||||
padding: 3px 0;
|
||||
text-align: center;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#menuBar1 #nameControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar1 #nameControl #eventName {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#menuBar1 #replayControl {
|
||||
float: right;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
#menuBar1 #scaleControl {
|
||||
float: right;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
#menuBar2 {
|
||||
width: 100%;
|
||||
padding: 3px 0;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
#menuBar2 div {
|
||||
text-align: left;
|
||||
float: left;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
#menuBar2 #closeWindow {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#menuBar1:after,
|
||||
#menuBar2:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#videoBar1 div {
|
||||
text-align: center;
|
||||
float: center;
|
||||
}
|
||||
|
||||
#videoBar1 #prevEvent {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#videoBar1 #dlEvent {
|
||||
float: center;
|
||||
}
|
||||
|
||||
#videoBar1 #nextEvent {
|
||||
float: right;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#imageFeed {
|
||||
|
@ -184,14 +139,16 @@ span.noneCue {
|
|||
|
||||
#progressBar {
|
||||
position: relative;
|
||||
top: -1.5em;
|
||||
height: 1.5em;
|
||||
margin: 0 auto -1.5em auto;
|
||||
top: -1.25em;
|
||||
height: 1.25em;
|
||||
margin: 0 auto -1.25em auto;
|
||||
}
|
||||
|
||||
#progressBar .progressBox {
|
||||
height: 1.5em;
|
||||
transition: width .1s;
|
||||
height: 100%;
|
||||
background: rgba(170, 170, 170, .7);
|
||||
border-radius: 0 0 .3em .3em;
|
||||
}
|
||||
|
||||
#eventStills {
|
||||
|
@ -223,6 +180,7 @@ span.noneCue {
|
|||
}
|
||||
|
||||
#eventImagePanel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -267,7 +225,7 @@ span.noneCue {
|
|||
|
||||
#eventImageNav {
|
||||
position: relative;
|
||||
margin: 4px 0 0 0;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
#eventImageNav input {
|
||||
|
@ -276,20 +234,20 @@ span.noneCue {
|
|||
}
|
||||
|
||||
#thumbsSliderPanel {
|
||||
width: 400px;
|
||||
margin: 4px auto 0;
|
||||
background: #888888;
|
||||
padding: 1px;
|
||||
width: 80%;
|
||||
margin: 0px auto 4px auto;
|
||||
}
|
||||
|
||||
#thumbsSlider {
|
||||
width: 400px;
|
||||
height: 10px;
|
||||
background: #dddddd;
|
||||
width: 100%;
|
||||
height: 1.25em;
|
||||
position: relative;
|
||||
top: -1.25em;
|
||||
margin: 0 0 -1.25em 0;
|
||||
}
|
||||
|
||||
#thumbsKnob {
|
||||
width: 8px;
|
||||
height: 10px;
|
||||
background-color: #444444;
|
||||
width: 1em;
|
||||
height: 100%;
|
||||
background-color: #999999;
|
||||
}
|
||||
|
|
|
@ -2,36 +2,6 @@
|
|||
background-color: #f8f8f8;;
|
||||
}
|
||||
|
||||
#controls {
|
||||
height: 16px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#controls a {
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
#controls #refreshLink {
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#controls #filterLink {
|
||||
position: absolute;
|
||||
left: 34%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#controls #timelineLink {
|
||||
position: absolute;
|
||||
left: 68%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#contentTable.major .colTime {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -44,3 +14,26 @@
|
|||
text-align: right;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#header #info, #header #pagination, #header #controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header #controls {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
#header #pagination {
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -1,33 +1,16 @@
|
|||
#scaleControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#controls {
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#controls a {
|
||||
width: 40px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
#firstLink {
|
||||
position: absolute;
|
||||
left: 13%;
|
||||
}
|
||||
|
||||
#prevLink {
|
||||
position: absolute;
|
||||
left: 37%;
|
||||
}
|
||||
|
||||
#nextLink {
|
||||
position: absolute;
|
||||
left: 63%;
|
||||
}
|
||||
|
||||
#lastLink {
|
||||
position: absolute;
|
||||
left: 87%;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
#monitors .alert {
|
||||
color: #ffa500;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#monitors .imageFeed {
|
||||
|
|
|
@ -36,3 +36,7 @@
|
|||
input[type=range]::-ms-tooltip {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#downloadVideo {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,25 @@
|
|||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#header #info, #header #headerButtons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header #headerButtons {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
#title {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
|
@ -15,20 +34,6 @@
|
|||
line-height: 20px;
|
||||
}
|
||||
|
||||
#listLink {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#closeLink {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#topPanel {
|
||||
position: relative;
|
||||
height: 220px;
|
||||
|
|
|
@ -1,37 +1,17 @@
|
|||
@import url(../control.css);
|
||||
|
||||
#menuBar {
|
||||
margin: 6px auto 4px;
|
||||
text-align: center;
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#menuBar #monitorName {
|
||||
float: left;
|
||||
#menuControls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#menuBar #closeControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#menuBar #menuControls {
|
||||
margin: 0 auto;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #controlControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #eventsControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #settingsControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #scaleControl {
|
||||
margin: 0 auto;
|
||||
#menuControls div {
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
#imageFeed{
|
||||
|
|
|
@ -373,11 +373,12 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
|
||||
#header {
|
||||
width: 100%;
|
||||
line-height: 24px;
|
||||
line-height: 1;
|
||||
text-align: left;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px 20px;
|
||||
padding: 5px 20px;
|
||||
margin: 0 auto 4px auto;
|
||||
font-weight: 300;
|
||||
border-bottom: 1px solid #000000;
|
||||
}
|
||||
|
||||
#header h2 {
|
||||
|
@ -407,7 +408,7 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
|
||||
#content {
|
||||
width: 96%;
|
||||
margin: 8px auto;
|
||||
margin: 0 auto 8px auto;
|
||||
line-height: 130%;
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -460,9 +461,9 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
button,
|
||||
input[type=button],
|
||||
input[type=submit] {
|
||||
background-color: #3498db;
|
||||
color: #fff;
|
||||
border-color: #3498db;
|
||||
background-color: #444444;
|
||||
color: #eeeeee;
|
||||
border-color: #444444;
|
||||
text-transform: uppercase;
|
||||
font-weight: 200;
|
||||
padding: 5px 10px;
|
||||
|
@ -472,7 +473,7 @@ input[type=submit] {
|
|||
button:hover,
|
||||
input[type=button]:hover,
|
||||
input[type=submit]:hover {
|
||||
background-color: #34a2ee;
|
||||
background-color: #555555;
|
||||
}
|
||||
|
||||
|
||||
|
@ -482,9 +483,9 @@ button:disabled,
|
|||
input[disabled],
|
||||
input[type=button]:disabled,
|
||||
input[type=submit]:disabled {
|
||||
color: #ffffff;
|
||||
background-color: #aaaaaa;
|
||||
border-color: #bbbbbb;
|
||||
color: #888888;
|
||||
background-color: #666666;
|
||||
border-color: #666666;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -534,8 +535,10 @@ input[type=submit]:disabled {
|
|||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
||||
.table-striped > tbody > tr:nth-of-type(2n+1) {
|
||||
background: none;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.table-hover>tbody>tr:hover {
|
||||
background-color: #444444;
|
||||
}
|
||||
|
|
|
@ -12,91 +12,63 @@
|
|||
|
||||
.alarmCue {
|
||||
background-color: #222222;
|
||||
height: 1.5em;
|
||||
height: 1.25em;
|
||||
text-align: left;
|
||||
margin: 0 auto 0 auto;
|
||||
border-radius: 0 0 .3em .3em;
|
||||
}
|
||||
|
||||
.alarmCue span {
|
||||
background-color:red;
|
||||
height: 1.5em;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
span.noneCue {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#eventVideo {
|
||||
display: inline-block;
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#dataBar {
|
||||
width: 100%;
|
||||
margin: 2px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#dataBar #dataTable {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
#dataBar #dataTable td {
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
flex-wrap:wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#menuBar1 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
padding: 3px 0;
|
||||
text-align: center;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#menuBar1 #nameControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar1 #nameControl #eventName {
|
||||
margin-right: 4px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
|
||||
#menuBar1 #replayControl {
|
||||
float: right;
|
||||
margin-left: 8px;
|
||||
margin: 0 4px 0 auto;
|
||||
}
|
||||
|
||||
#menuBar1 #scaleControl {
|
||||
float: right;
|
||||
margin-left: 8px;
|
||||
#menuBar1 div {
|
||||
margin: auto 5px;
|
||||
}
|
||||
|
||||
#menuBar2 {
|
||||
width: 100%;
|
||||
padding: 3px 0;
|
||||
margin-bottom: 4px;
|
||||
#nameControl input[type="button"]{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#menuBar2 div {
|
||||
text-align: left;
|
||||
float: left;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
#menuBar2 #closeWindow {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#menuBar1:after,
|
||||
#menuBar2:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
#eventVideo {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#imageFeed {
|
||||
|
@ -166,14 +138,16 @@ span.noneCue {
|
|||
|
||||
#progressBar {
|
||||
position: relative;
|
||||
top: -1.5em;
|
||||
height: 1.5em;
|
||||
margin: 0 auto -1.5em auto;
|
||||
top: -1.25em;
|
||||
height: 1.25em;
|
||||
margin: 0 auto -1.25em auto;
|
||||
}
|
||||
|
||||
#progressBar .progressBox {
|
||||
height: 1.5em;
|
||||
transition: width .1s;
|
||||
height: 100%;
|
||||
background: rgba(170, 170, 170, .7);
|
||||
border-radius: 0 0 .3em .3em;
|
||||
}
|
||||
|
||||
#eventStills {
|
||||
|
@ -206,6 +180,7 @@ span.noneCue {
|
|||
}
|
||||
|
||||
#eventImagePanel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -250,7 +225,7 @@ span.noneCue {
|
|||
|
||||
#eventImageNav {
|
||||
position: relative;
|
||||
margin: 4px 0 0 0;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
#eventImageNav input {
|
||||
|
@ -259,25 +234,20 @@ span.noneCue {
|
|||
}
|
||||
|
||||
#thumbsSliderPanel {
|
||||
width: 400px;
|
||||
margin: 4px auto 0;
|
||||
background: #888888;
|
||||
padding: 1px;
|
||||
width: 80%;
|
||||
margin: 0px auto 4px auto;
|
||||
}
|
||||
|
||||
#thumbsSlider {
|
||||
width: 400px;
|
||||
height: 10px;
|
||||
background: #dddddd;
|
||||
}
|
||||
|
||||
#eventVideo {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 1.25em;
|
||||
position: relative;
|
||||
top: -1.25em;
|
||||
margin: 0 0 -1.25em 0;
|
||||
}
|
||||
|
||||
#thumbsKnob {
|
||||
width: 8px;
|
||||
height: 10px;
|
||||
background-color: #444444;
|
||||
width: 1em;
|
||||
height: 100%;
|
||||
background-color: #999999;
|
||||
}
|
||||
|
|
|
@ -2,36 +2,6 @@
|
|||
background-color: #2e2e2e;
|
||||
}
|
||||
|
||||
#controls {
|
||||
height: 16px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#controls a {
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
#controls #refreshLink {
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#controls #filterLink {
|
||||
position: absolute;
|
||||
left: 34%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#controls #timelineLink {
|
||||
position: absolute;
|
||||
left: 68%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#contentTable.major .colTime {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -44,3 +14,26 @@
|
|||
text-align: right;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#header #info, #header #pagination, #header #controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header #controls {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
#header #pagination {
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -1,33 +1,16 @@
|
|||
#scaleControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#controls {
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#controls a {
|
||||
width: 40px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
#firstLink {
|
||||
position: absolute;
|
||||
left: 13%;
|
||||
}
|
||||
|
||||
#prevLink {
|
||||
position: absolute;
|
||||
left: 37%;
|
||||
}
|
||||
|
||||
#nextLink {
|
||||
position: absolute;
|
||||
left: 63%;
|
||||
}
|
||||
|
||||
#lastLink {
|
||||
position: absolute;
|
||||
left: 87%;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
#monitors .alert {
|
||||
color: #ffa500;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#monitors .imageFeed {
|
||||
|
|
|
@ -36,3 +36,7 @@
|
|||
input[type=range]::-ms-tooltip {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#downloadVideo {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,25 @@
|
|||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#header #info, #header #headerButtons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header #headerButtons {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
#title {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
|
@ -15,20 +34,6 @@
|
|||
line-height: 20px;
|
||||
}
|
||||
|
||||
#listLink {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#closeLink {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#topPanel {
|
||||
position: relative;
|
||||
height: 220px;
|
||||
|
|
|
@ -1,37 +1,17 @@
|
|||
@import url(../control.css);
|
||||
|
||||
#menuBar {
|
||||
margin: 6px auto 4px;
|
||||
text-align: center;
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#menuBar #monitorName {
|
||||
float: left;
|
||||
#menuControls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#menuBar #closeControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#menuBar #menuControls {
|
||||
margin: 0 auto;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #controlControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #eventsControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #settingsControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #scaleControl {
|
||||
margin: 0 auto;
|
||||
#menuControls div {
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
#imageFeed{
|
||||
|
|
|
@ -368,11 +368,11 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
|
||||
#header {
|
||||
width: 100%;
|
||||
line-height: 24px;
|
||||
line-height: 1;
|
||||
text-align: left;
|
||||
background-color: #383836;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px 20px;
|
||||
padding: 5px 20px;
|
||||
margin: 0 auto 4px auto;
|
||||
color: #f2f2f2;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
@ -410,7 +410,7 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
|
||||
#content {
|
||||
width: 96%;
|
||||
margin: 8px auto;
|
||||
margin: 0 auto 8px auto;
|
||||
line-height: 130%;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -12,98 +12,71 @@
|
|||
|
||||
.alarmCue {
|
||||
background-color: #222222;
|
||||
height: 1.5em;
|
||||
height: 1.25em;
|
||||
text-align: left;
|
||||
margin: 0 auto 0 auto;
|
||||
border-radius: 0 0 .3em .3em;
|
||||
}
|
||||
|
||||
.alarmCue span {
|
||||
background-color:red;
|
||||
height: 1.5em;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
span.noneCue {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#dataBar {
|
||||
width: 100%;
|
||||
margin: 2px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#dataBar #dataTable {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
#dataBar #dataTable td {
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
flex-wrap:wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#menuBar1 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
padding: 3px 0;
|
||||
text-align: center;
|
||||
clear: both;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
#menuBar1 #nameControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar1 #nameControl #eventName {
|
||||
margin-right: 4px;
|
||||
#menuBar1 input, #menuBar1 select {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
#menuBar1 #replayControl {
|
||||
float: right;
|
||||
margin-left: 8px;
|
||||
margin: 0 4px 0 auto;
|
||||
}
|
||||
|
||||
#menuBar1 #scaleControl {
|
||||
float: right;
|
||||
margin-left: 8px;
|
||||
#menuBar1 div {
|
||||
margin: auto 5px;
|
||||
}
|
||||
|
||||
#menuBar2 {
|
||||
width: 100%;
|
||||
padding: 3px 0;
|
||||
margin-bottom: 4px;
|
||||
#nameControl input[type="button"]{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#menuBar2 div {
|
||||
text-align: left;
|
||||
float: left;
|
||||
padding: 0 12px;
|
||||
#eventVideo {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#menuBar2 #closeWindow {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
#menuBar1:after,
|
||||
#menuBar2:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#menuBar1:after,
|
||||
#menuBar2:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
#imageFeed {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
@ -177,14 +150,16 @@ span.noneCue {
|
|||
|
||||
#progressBar {
|
||||
position: relative;
|
||||
top: -1.5em;
|
||||
height: 1.5em;
|
||||
margin: 0 auto -1.5em auto;
|
||||
top: -1.25em;
|
||||
height: 1.25em;
|
||||
margin: 0 auto -1.25em auto;
|
||||
}
|
||||
|
||||
#progressBar .progressBox {
|
||||
height: 1.5em;
|
||||
transition: width .1s;
|
||||
height: 100%;
|
||||
background: rgba(170, 170, 170, .7);
|
||||
border-radius: 0 0 .3em .3em;
|
||||
}
|
||||
|
||||
#eventStills {
|
||||
|
@ -217,6 +192,7 @@ span.noneCue {
|
|||
}
|
||||
|
||||
#eventImagePanel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -261,7 +237,7 @@ span.noneCue {
|
|||
|
||||
#eventImageNav {
|
||||
position: relative;
|
||||
margin: 4px 0 0 0;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
#eventImageNav input {
|
||||
|
@ -270,82 +246,20 @@ span.noneCue {
|
|||
}
|
||||
|
||||
#thumbsSliderPanel {
|
||||
width: 400px;
|
||||
margin: 4px auto 0;
|
||||
background: #888888;
|
||||
padding: 1px;
|
||||
width: 80%;
|
||||
margin: 0px auto 4px auto;
|
||||
}
|
||||
|
||||
#thumbsSlider {
|
||||
width: 400px;
|
||||
height: 10px;
|
||||
background: #dddddd;
|
||||
width: 100%;
|
||||
height: 1.25em;
|
||||
position: relative;
|
||||
top: -1.25em;
|
||||
margin: 0 0 -1.25em 0;
|
||||
}
|
||||
|
||||
#thumbsKnob {
|
||||
width: 8px;
|
||||
height: 10px;
|
||||
background-color: #444444;
|
||||
}
|
||||
#eventVideo {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#video-controls {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 5px;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity .3s;
|
||||
-moz-transition: opacity .3s;
|
||||
-o-transition: opacity .3s;
|
||||
-ms-transition: opacity .3s;
|
||||
transition: opacity .3s;
|
||||
background-image: linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
|
||||
background-image: -o-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
|
||||
background-image: -moz-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
|
||||
background-image: -ms-linear-gradient(bottom, rgb(3,113,168) 13%, rgb(0,136,204) 100%);
|
||||
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0.13, rgb(3,113,168)),
|
||||
color-stop(1, rgb(0,136,204))
|
||||
);
|
||||
}
|
||||
|
||||
#eventVideo:hover #video-controls {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
button {
|
||||
background: rgba(0,0,0,.5);
|
||||
border: 0;
|
||||
color: #EEE;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-o-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#seekbar {
|
||||
width: 360px;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#volume-bar {
|
||||
width: 60px;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
width: 1em;
|
||||
height: 100%;
|
||||
background-color: #999999;
|
||||
}
|
||||
|
|
|
@ -2,36 +2,6 @@
|
|||
background-color: #f8f8f8;;
|
||||
}
|
||||
|
||||
#controls {
|
||||
height: 16px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#controls a {
|
||||
width: 32%;
|
||||
}
|
||||
|
||||
#controls #refreshLink {
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#controls #filterLink {
|
||||
position: absolute;
|
||||
left: 34%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#controls #timelineLink {
|
||||
position: absolute;
|
||||
left: 68%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#contentTable.major .colTime {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -44,3 +14,26 @@
|
|||
text-align: right;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#header #info, #header #pagination, #header #controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header #controls {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
#header #pagination {
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -6,29 +6,11 @@
|
|||
width: 80%;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#controls a {
|
||||
width: 40px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
#firstLink {
|
||||
position: absolute;
|
||||
left: 13%;
|
||||
}
|
||||
|
||||
#prevLink {
|
||||
position: absolute;
|
||||
left: 37%;
|
||||
}
|
||||
|
||||
#nextLink {
|
||||
position: absolute;
|
||||
left: 63%;
|
||||
}
|
||||
|
||||
#lastLink {
|
||||
position: absolute;
|
||||
left: 87%;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
display: inline-flex;
|
||||
border: 1px solid black;
|
||||
width: 25%;
|
||||
padding: 9px;
|
||||
padding: 4px;
|
||||
}
|
||||
#ScaleDiv label,
|
||||
#SpeedDiv label {
|
||||
|
@ -42,3 +42,7 @@ input[type=range]::-ms-tooltip {
|
|||
color: white;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
#downloadVideo {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,25 @@
|
|||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#header h2, #header a {
|
||||
line-height: 1.1;
|
||||
margin:5px 0 0 0;
|
||||
}
|
||||
|
||||
#header #info, #header #headerButtons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#header #headerButtons {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
#title {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
|
@ -15,20 +34,6 @@
|
|||
line-height: 20px;
|
||||
}
|
||||
|
||||
#listLink {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#closeLink {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 20px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
#topPanel {
|
||||
position: relative;
|
||||
height: 220px;
|
||||
|
|
|
@ -1,37 +1,17 @@
|
|||
@import url(../control.css);
|
||||
|
||||
#menuBar {
|
||||
margin: 6px auto 4px;
|
||||
text-align: center;
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#menuBar #monitorName {
|
||||
float: left;
|
||||
#menuControls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#menuBar #closeControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#menuBar #menuControls {
|
||||
margin: 0 auto;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #controlControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #eventsControl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #settingsControl {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#menuBar #menuControls #scaleControl {
|
||||
margin: 0 auto;
|
||||
#menuControls div {
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
#imageFeed{
|
||||
|
|
|
@ -45,7 +45,7 @@ $scales = array(
|
|||
'12.5' => '1/8x',
|
||||
);
|
||||
|
||||
if (isset($_REQUEST['view'])) unset($scales[$_REQUEST['view'] == 'event' ? '' : 'auto']); //Remove the option we aren't using on montage or event
|
||||
if (isset($_REQUEST['view'])) unset($scales[$_REQUEST['view'] == 'montage' ? 'auto' : '']); //Only use fixed width/Height on montage
|
||||
|
||||
$bandwidth_options = array(
|
||||
'high' => translate('High'),
|
||||
|
@ -56,6 +56,7 @@ $bandwidth_options = array(
|
|||
switch ( $_COOKIE['zmBandwidth'] ) {
|
||||
case 'high' : {
|
||||
define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_H_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
|
||||
define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_H_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes
|
||||
define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_H_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
|
||||
define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_H_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
||||
define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_H_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
||||
|
@ -73,6 +74,7 @@ switch ( $_COOKIE['zmBandwidth'] ) {
|
|||
break;
|
||||
} case 'medium' : {
|
||||
define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_M_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
|
||||
define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_M_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes
|
||||
define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_M_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
|
||||
define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_M_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
||||
define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_M_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
||||
|
@ -90,6 +92,7 @@ switch ( $_COOKIE['zmBandwidth'] ) {
|
|||
break;
|
||||
} case 'low' : {
|
||||
define( 'ZM_WEB_REFRESH_MAIN', ZM_WEB_L_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes
|
||||
define( 'ZM_WEB_REFRESH_NAVBAR', ZM_WEB_L_REFRESH_NAVBAR ); // How often (in seconds) the nav header refreshes
|
||||
define( 'ZM_WEB_REFRESH_CYCLE', ZM_WEB_L_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor
|
||||
define( 'ZM_WEB_REFRESH_IMAGE', ZM_WEB_L_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming)
|
||||
define( 'ZM_WEB_REFRESH_STATUS', ZM_WEB_L_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window
|
||||
|
|
|
@ -853,7 +853,7 @@ function exportFileList( $eid, $exportDetail, $exportFrames, $exportImages, $exp
|
|||
return( array_values( $exportFileList ) );
|
||||
}
|
||||
|
||||
function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat )
|
||||
function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat, $exportStructure = false )
|
||||
{
|
||||
|
||||
if ( canView( 'Events' ) && !empty($eids) )
|
||||
|
@ -907,8 +907,12 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo
|
|||
{
|
||||
$archive = ZM_DIR_EXPORTS."/".$export_root.".tar.gz";
|
||||
@unlink( $archive );
|
||||
$command = "tar --create --gzip --file=$archive --files-from=$listFile";
|
||||
exec( escapeshellcmd( $command ), $output, $status );
|
||||
if ($exportStructure == 'flat') { //strip file paths if we choose
|
||||
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile)." --xform='s#^.+/##x'";
|
||||
} else {
|
||||
$command = "nice -10 tar --create --gzip --file=".escapeshellarg($archive)." --files-from=".escapeshellarg($listFile);
|
||||
}
|
||||
exec( $command, $output, $status );
|
||||
if ( $status )
|
||||
{
|
||||
Error( "Command '$command' returned with status $status" );
|
||||
|
@ -921,7 +925,11 @@ function exportEvents( $eids, $exportDetail, $exportFrames, $exportImages, $expo
|
|||
{
|
||||
$archive = ZM_DIR_EXPORTS."/".$export_root.".zip";
|
||||
@unlink( $archive );
|
||||
$command = "cat ".escapeshellarg($listFile)." | zip -q ".escapeshellarg($archive)." -@";
|
||||
if ($exportStructure == 'flat') {
|
||||
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q -j ".escapeshellarg($archive)." -@";
|
||||
} else {
|
||||
$command = "cat ".escapeshellarg($listFile)." | nice -10 zip -q ".escapeshellarg($archive)." -@";
|
||||
}
|
||||
//cat zmFileList.txt | zip -q zm_export.zip -@
|
||||
//-bash: zip: command not found
|
||||
|
||||
|
|
|
@ -159,26 +159,29 @@ if ( file_exists( "skins/$skin/css/$css/graphics/favicon.ico" ) ) {
|
|||
<?php
|
||||
} // end function xhtmlHeaders( $file, $title )
|
||||
|
||||
function getNavBarHTML() {
|
||||
function getNavBarHTML($reload = null) {
|
||||
|
||||
$versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':'';
|
||||
|
||||
|
||||
ob_start();
|
||||
global $running;
|
||||
if ( $running == null )
|
||||
$running = daemonCheck();
|
||||
$status = $running?translate('Running'):translate('Stopped');
|
||||
global $user;
|
||||
global $bandwidth_options;
|
||||
global $view;
|
||||
global $filterQuery;
|
||||
if (!$filterQuery) {
|
||||
parseFilter( $_REQUEST['filter'] );
|
||||
$filterQuery = $_REQUEST['filter']['query'];
|
||||
}
|
||||
if ($reload === null) {
|
||||
ob_start();
|
||||
if ( $running == null )
|
||||
$running = daemonCheck();
|
||||
$status = $running?translate('Running'):translate('Stopped');
|
||||
?>
|
||||
<noscript>
|
||||
<div style="background-color:red;color:white;font-size:x-large;">
|
||||
ZoneMinder requires Javascript. Please enable Javascript in your browser for this site.
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<div class="navbar navbar-inverse navbar-static-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
|
@ -212,7 +215,7 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
|
|||
<li><a href="?view=devices">Devices</a></li>
|
||||
<?php } ?>
|
||||
<li><a href="?view=groups"<?php echo $view=='groups'?' class="selected"':''?>><?php echo translate('Groups') ?></a></li>
|
||||
<li><a href="?view=filter"<?php echo $view=='filter'?' class="selected"':''?>><?php echo translate('Filters') ?></a></li>
|
||||
<li><a href="?view=filter<?php echo $filterQuery ?>"<?php echo $view=='filter'?' class="selected"':''?>><?php echo translate('Filters') ?></a></li>
|
||||
|
||||
<?php
|
||||
if ( canView( 'Stream' ) ) {
|
||||
|
@ -221,9 +224,23 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
|
|||
<li><a href="?view=montage"<?php echo $view=='montage'?' class="selected"':''?>><?php echo translate('Montage') ?></a></li>
|
||||
<?php
|
||||
}
|
||||
if (isset($_REQUEST['filter']['Query']['terms'])) {
|
||||
$terms = $_REQUEST['filter']['Query']['terms'];
|
||||
$count = 0;
|
||||
foreach ($terms as $term) {
|
||||
if ($term['attr'] == "StartDateTime") {
|
||||
$count += 1;
|
||||
if ($term['op'] == '>=') $minTime = $term['val'];
|
||||
if ($term['op'] == '<=') $maxTime = $term['val'];
|
||||
}
|
||||
}
|
||||
if ($count == 2) {
|
||||
$montageReviewQuery = '&minTime='.$minTime.'&maxTime='.$maxTime;
|
||||
}
|
||||
}
|
||||
if ( canView('Events') ) {
|
||||
?>
|
||||
<li><a href="?view=montagereview"<?php echo $view=='montagereview'?' class="selected"':''?>><?php echo translate('MontageReview')?></a></li>
|
||||
<li><a href="?view=montagereview<?php echo isset($montageReviewQuery)?'&fit=1'.$montageReviewQuery.'&live=0':'' ?>"<?php echo $view=='montagereview'?' class="selected"':''?>><?php echo translate('MontageReview')?></a></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
@ -243,7 +260,11 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
|
|||
</div>
|
||||
</div><!-- End .navbar-collapse -->
|
||||
</div> <!-- End .container-fluid -->
|
||||
<div class="container-fluid">
|
||||
<?php
|
||||
}//end reload null. Runs on full page load
|
||||
if ($reload == 'reload') ob_start();
|
||||
?>
|
||||
<div id="reload" class="container-fluid">
|
||||
<div class="pull-left">
|
||||
<?php echo makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', $bandwidth_options[$_COOKIE['zmBandwidth']] . ' ' . translate('BandwidthHead'), ($user && $user['MaxBandwidth'] != 'low' ) ) ?>
|
||||
</div>
|
||||
|
@ -277,9 +298,11 @@ if ( ZM_OPT_X10 && canView( 'Devices' ) ) { ?>
|
|||
echo ' ' . ZM_PATH_MAP .': '. getDiskPercent(ZM_PATH_MAP).'%';
|
||||
?></li>
|
||||
</ul>
|
||||
</div> <!-- End .footer -->
|
||||
|
||||
</div> <!-- End .navbar .navbar-default -->
|
||||
</div> <!-- End .footer/reload -->
|
||||
<?php
|
||||
if ($reload == 'reload') return( ob_get_clean() );
|
||||
?>
|
||||
</div><!-- End .navbar .navbar-default -->
|
||||
<?php
|
||||
return( ob_get_clean() );
|
||||
} // end function getNavBarHTML()
|
||||
|
|
|
@ -104,6 +104,10 @@ function parseFilterToTree( $filter ) {
|
|||
$sqlValue = "E.StartTime";
|
||||
$dtAttr = true;
|
||||
break;
|
||||
case 'StartDateTime':
|
||||
$sqlValue = "E.StartTime";
|
||||
$dtAttr = true;
|
||||
break;
|
||||
case 'Date':
|
||||
$sqlValue = "to_days( E.StartTime )";
|
||||
$dtAttr = true;
|
||||
|
@ -196,6 +200,9 @@ function parseFilterToTree( $filter ) {
|
|||
case 'DateTime':
|
||||
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
|
||||
break;
|
||||
case 'StartDateTime':
|
||||
$value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'";
|
||||
break;
|
||||
case 'Date':
|
||||
$value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )";
|
||||
break;
|
||||
|
@ -359,7 +366,7 @@ function parseTreeToFilter( $tree )
|
|||
$level = 0;
|
||||
_parseTreeToFilter( $tree, $terms, $level );
|
||||
}
|
||||
return( array( 'terms' => $terms ) );
|
||||
return( array( 'Query' => array( 'terms' => $terms ) ) );
|
||||
}
|
||||
|
||||
function parseTreeToQuery( $tree )
|
||||
|
@ -461,7 +468,7 @@ function extractDatetimeRange( &$tree, &$minTime, &$maxTime, &$expandable )
|
|||
|
||||
function appendDatetimeRange( &$tree, $minTime, $maxTime=false )
|
||||
{
|
||||
$attrNode = array( 'data'=>array( 'type'=>'attr', 'value'=>'DateTime', 'sqlValue'=>'E.StartTime', 'dtAttr'=>true ), 'count'=>0 );
|
||||
$attrNode = array( 'data'=>array( 'type'=>'attr', 'value'=>'StartDateTime', 'sqlValue'=>'E.StartTime', 'dtAttr'=>true ), 'count'=>0 );
|
||||
$valNode = array( 'data'=>array( 'type'=>'val', 'value'=>$minTime, 'sqlValue'=>$minTime ), 'count'=>0 );
|
||||
$opNode = array( 'data'=>array( 'type'=>'op', 'value'=>'>=', 'sqlValue'=>'>=' ), 'count'=>2, 'left'=>$attrNode, 'right'=>$valNode );
|
||||
if ( isset($tree) )
|
||||
|
@ -476,7 +483,7 @@ function appendDatetimeRange( &$tree, $minTime, $maxTime=false )
|
|||
|
||||
if ( $maxTime )
|
||||
{
|
||||
$attrNode = array( 'data'=>array( 'type'=>'attr', 'value'=>'DateTime', 'sqlValue'=>'E.StartTime', 'dtAttr'=>true ), 'count'=>0 );
|
||||
$attrNode = array( 'data'=>array( 'type'=>'attr', 'value'=>'StartDateTime', 'sqlValue'=>'E.StartTime', 'dtAttr'=>true ), 'count'=>0 );
|
||||
$valNode = array( 'data'=>array( 'type'=>'val', 'value'=>$maxTime, 'sqlValue'=>$maxTime ), 'count'=>0 );
|
||||
$opNode = array( 'data'=>array( 'type'=>'op', 'value'=>'<=', 'sqlValue'=>'<=' ), 'count'=>2, 'left'=>$attrNode, 'right'=>$valNode );
|
||||
$cnjNode = array( 'data'=>array( 'type'=>'cnj', 'value'=>'and', 'sqlValue'=>'and' ), 'count'=>2+$tree['count']+$opNode['count'], 'left'=>$tree, 'right'=>$opNode );
|
||||
|
|
|
@ -33,6 +33,7 @@ var popupSizes = {
|
|||
'device': { 'width': 260, 'height': 150 },
|
||||
'devices': { 'width': 400, 'height': 240 },
|
||||
'donate': { 'width': 500, 'height': 280 },
|
||||
'download': { 'width': 350, 'height': 215 },
|
||||
'event': { 'addWidth': 108, 'minWidth': 496, 'addHeight': 230, 'minHeight': 540 },
|
||||
'eventdetail': { 'width': 600, 'height': 420 },
|
||||
'events': { 'width': 1220, 'height': 780 },
|
||||
|
|
|
@ -182,6 +182,22 @@ function refreshParentWindow() {
|
|||
}
|
||||
}
|
||||
|
||||
if (currentView !='none') {
|
||||
$j.ajaxSetup ({timeout: AJAX_TIMEOUT }); //sets timeout for all getJSON.
|
||||
|
||||
$j(document).ready(function() {
|
||||
if ($j('.navbar').length) setInterval(getNavBar, navBarRefresh)
|
||||
});
|
||||
|
||||
function getNavBar () {
|
||||
$j.getJSON(thisUrl + '?view=request&request=status&entity=navBar', setNavBar);
|
||||
}
|
||||
|
||||
function setNavBar (data) {
|
||||
$j('#reload').replaceWith(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
//Shows a message if there is an error in the streamObj or the stream doesn't exist. Returns true if error, false otherwise.
|
||||
function checkStreamForErrors( funcName, streamObj ) {
|
||||
if ( !streamObj ) {
|
||||
|
@ -333,3 +349,36 @@ function changeFilter( e ) {
|
|||
Cookie.write( e.name, e.value, { duration: 10*365 } );
|
||||
window.location = window.location;
|
||||
}
|
||||
|
||||
var resizeTimer;
|
||||
|
||||
function endOfResize(e) {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(changeScale, 250);
|
||||
}
|
||||
|
||||
function scaleToFit (baseWidth, baseHeight, scaleEl, bottomEl) {
|
||||
$j(window).on('resize', endOfResize) //set delayed scaling when Scale to Fit is selected
|
||||
let ratio = baseWidth / baseHeight;
|
||||
let container = $j('#content');
|
||||
let viewPort = $j(window);
|
||||
// jquery does not provide a bottom offet, and offset dows not include margins. outerHeight true minus false gives total vertical margins.
|
||||
let bottomLoc = bottomEl.offset().top + (bottomEl.outerHeight(true) - bottomEl.outerHeight()) + bottomEl.outerHeight(true);
|
||||
let newHeight = viewPort.height() - (bottomLoc - scaleEl.outerHeight(true))
|
||||
let newWidth = ratio * newHeight;
|
||||
if (newWidth > container.innerWidth()) {
|
||||
newWidth = container.innerWidth();
|
||||
newHeight = newWidth / ratio;
|
||||
}
|
||||
let autoScale = Math.round(newWidth / baseWidth * SCALE_BASE);
|
||||
let scales = $j('#scale option').map(function() {return parseInt($j(this).val());}).get();
|
||||
scales.shift();
|
||||
let closest;
|
||||
$j(scales).each(function () { //Set zms scale to nearest regular scale. Zoom does not like arbitrary scale values.
|
||||
if (closest == null || Math.abs(this - autoScale) < Math.abs(closest - autoScale)) {
|
||||
closest = this.valueOf();
|
||||
}
|
||||
});
|
||||
autoScale = closest;
|
||||
return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale};
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
?>
|
||||
var AJAX_TIMEOUT = <?php echo ZM_WEB_AJAX_TIMEOUT ?>;
|
||||
|
||||
var navBarRefresh = <?php echo 1000*ZM_WEB_REFRESH_NAVBAR ?>;
|
||||
|
||||
var currentView = '<?php echo $view ?>';
|
||||
var thisUrl = "<?php echo ZM_BASE_URL.$_SERVER['PHP_SELF'] ?>";
|
||||
var skinPath = "<?php echo ZM_SKIN_PATH ?>";
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
.vjs-tech {
|
||||
pointer-events: none;
|
||||
transition: transform .25s;
|
||||
}
|
||||
|
||||
.vjs-captions-button {
|
||||
|
|
|
@ -45,7 +45,7 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
|
|||
<div style="width:50%;position: absolute; top:0; left: 0;height: 100%;">
|
||||
<fieldset><legend>Enter by IP or URL</legend>
|
||||
<!--<input type="text" name="newMonitor[Name]" />-->
|
||||
<input type="url" name="newMonitor[Url]" oninput="probe(this);"/>
|
||||
<input type="text" name="newMonitor[Url]" oninput="probe(this);"/>
|
||||
</fieldset>
|
||||
<fieldset><legend>Import CSV Spreadsheet</legend>
|
||||
Spreadsheet should have the following format:<br/>
|
||||
|
|
|
@ -208,11 +208,11 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
<?php
|
||||
if ( ZM_WEB_ID_ON_CONSOLE ) {
|
||||
?>
|
||||
<td class="colId"><?php echo makePopupLink( '?view=watch&mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Id'], ($monitor['Function'] != 'None') && canView('Stream') ) ?></td>
|
||||
<td class="colId"><a <?php echo (canView('Stream') && $running && $monitor['Function'] != 'None' ? 'href="?view=watch&mid='.$monitor['Id'].'">' : '>') . $monitor['Id'] ?></a></td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<td class="colName"><?php echo makePopupLink( '?view=watch&mid='.$monitor['Id'], 'zmWatch'.$monitor['Id'], array( 'watch', reScale( $monitor['Width'], $scale ), reScale( $monitor['Height'], $scale ) ), $monitor['Name'], ($monitor['Function'] != 'None') && canView('Stream') ) ?></td>
|
||||
<td class="colName"><a <?php echo (canView('Stream') && $monitor['Function'] != 'None' ? 'href="?view=watch&mid='.$monitor['Id'].'">' : '>') . $monitor['Name'] ?></a></td>
|
||||
<td class="colFunction">
|
||||
<?php echo makePopupLink( '?view=function&mid='.$monitor['Id'], 'zmFunction', 'function', '<span class="'.$fclass.'">'.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'</span>', canEdit( 'Monitors' ) ) ?><br/>
|
||||
<?php echo $monitor['CaptureFPS'] . ( ( $monitor['Function'] == 'Mocord' or $monitor['Function'] == 'Modect' ) ? ' / ' . $monitor['AnalysisFPS'] : '' ) . ' FPS' ?>
|
||||
|
@ -245,8 +245,8 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
|
||||
foreach ( array_keys( $eventCounts ) as $i ) {
|
||||
?>
|
||||
<td class="colEvents"><?php echo makePopupLink( '?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$monitor['eventCounts'][$i]['filter']['query'], $eventsWindow, ZM_WEB_EVENTS_VIEW,
|
||||
$monitor[$i.'Events'] . '<br/>' . human_filesize($monitor[$i.'EventDiskSpace']), canView( 'Events' ) ) ?></td>
|
||||
<td class="colEvents"><a <?php echo (canView('Events') ? 'href="?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$monitor['eventCounts'][$i]['filter']['query'].'">' : '') .
|
||||
$monitor[$i.'Events'] . '<br/>' . human_filesize($monitor[$i.'EventDiskSpace']) ?></a></td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
@ -281,9 +281,8 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
|
|||
parseFilter( $eventCounts[$i]['filter'] );
|
||||
?>
|
||||
<td class="colEvents">
|
||||
<?php echo makePopupLink( '?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$eventCounts[$i]['filter']['query'], $eventsWindow, ZM_WEB_EVENTS_VIEW,
|
||||
$eventCounts[$i]['totalevents'].'<br/>'.human_filesize($eventCounts[$i]['totaldiskspace']), canView( 'Events' ) ) ?>
|
||||
</td>
|
||||
<a <?php echo (canView('Events') ? 'href="?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$eventCounts[$i]['filter']['query'].'">' : '') .
|
||||
$eventCounts[$i]['totalevents'].'<br/>'.human_filesize($eventCounts[$i]['totaldiskspace']) ?></a></td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -31,52 +31,26 @@ if ( empty($_REQUEST['mode']) ) {
|
|||
} else {
|
||||
$mode = validHtmlStr($_REQUEST['mode']);
|
||||
}
|
||||
ob_start();
|
||||
include('_monitor_filters.php');
|
||||
$filterbar = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$group_id = 0;
|
||||
if ( isset($_REQUEST['group']) ) {
|
||||
$group_id = $_REQUEST['group'];
|
||||
} else if ( isset($_COOKIE['zmGroup'] ) ) {
|
||||
$group_id = $_COOKIE['zmGroup'];
|
||||
}
|
||||
|
||||
$subgroup_id = 0;
|
||||
if ( isset($_REQUEST['subgroup']) ) {
|
||||
$subgroup_id = $_REQUEST['subgroup'];
|
||||
} else if ( isset($_COOKIE['zmSubGroup'] ) ) {
|
||||
$subgroup_id = $_COOKIE['zmSubGroup'];
|
||||
}
|
||||
$groupIds = null;
|
||||
if ( $group_id ) {
|
||||
$groupIds = array();
|
||||
if ( $group = dbFetchOne( 'SELECT MonitorIds FROM Groups WHERE Id = ?', NULL, array($group_id) ) )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = explode( ',', $group['MonitorIds'] );
|
||||
if ( $subgroup_id ) {
|
||||
if ( $group = dbFetchOne( 'SELECT MonitorIds FROM Groups WHERE Id = ?', NULL, array($subgroup_id) ) )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = array_merge( $groupIds, explode( ',', $group['MonitorIds'] ) );
|
||||
} else {
|
||||
foreach ( dbFetchAll( 'SELECT MonitorIds FROM Groups WHERE ParentId = ?', NULL, array($group_id) ) as $group )
|
||||
if ( $group['MonitorIds'] )
|
||||
$groupIds = array_merge( $groupIds, explode( ',', $group['MonitorIds'] ) );
|
||||
}
|
||||
}
|
||||
$groupSql = '';
|
||||
if ( $groupIds )
|
||||
$groupSql = " and find_in_set( Id, '".implode( ',', $groupIds )."' )";
|
||||
|
||||
$sql = "SELECT * FROM Monitors WHERE Function != 'None'$groupSql ORDER BY Sequence";
|
||||
$monitors = array();
|
||||
$monIdx = 0;
|
||||
foreach( dbFetchAll( $sql ) as $row ) {
|
||||
if ( !visibleMonitor( $row['Id'] ) )
|
||||
$monitors = array();
|
||||
foreach( $displayMonitors as &$row ) {
|
||||
if ( $row['Function'] == 'None' )
|
||||
continue;
|
||||
if ( isset($_REQUEST['mid']) && $row['Id'] == $_REQUEST['mid'] )
|
||||
$monIdx = count($monitors);
|
||||
|
||||
$row['ScaledWidth'] = reScale( $row['Width'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
$row['ScaledHeight'] = reScale( $row['Height'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
$row['PopupScale'] = reScale( SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
|
||||
|
||||
$row['connKey'] = generateConnKey();
|
||||
$monitors[] = new Monitor( $row );
|
||||
}
|
||||
} # end foreach Monitor
|
||||
|
||||
if ( $monitors ) {
|
||||
$monitor = $monitors[$monIdx];
|
||||
|
@ -103,22 +77,7 @@ xhtmlHeaders(__FILE__, translate('CycleWatch') );
|
|||
<?php } ?>
|
||||
</div>
|
||||
<div class="controlHeader">
|
||||
<span id="groupControl"><label><?php echo translate('Group') ?>:</label>
|
||||
<?php
|
||||
|
||||
$groups = array(0=>'All');
|
||||
foreach ( Group::find_all( array('ParentId'=>null) ) as $Group ) {
|
||||
$groups[$Group->Id()] = $Group->Name();
|
||||
}
|
||||
echo htmlSelect( 'group', $groups, $group_id, 'changeGroup(this);' );
|
||||
$groups = array(0=>'All');
|
||||
if ( $group_id ) {
|
||||
foreach ( Group::find_all( array('ParentId'=>$group_id) ) as $Group ) {
|
||||
$groups[$Group->Id()] = $Group->Name();
|
||||
}
|
||||
}
|
||||
echo htmlSelect( 'subgroup', $groups, $subgroup_id, 'changeSubGroup(this);' );
|
||||
?>
|
||||
<?php echo $filterbar ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
//
|
||||
// ZoneMinder web export view file, $Date$, $Revision$
|
||||
// Copyright (C) 2001-2008 Philip Coombes
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( !canView('Events') ) {
|
||||
$view = 'error';
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($_SESSION['montageReviewFilter'])) { //Handles montageReview filter
|
||||
$eventsSql = 'SELECT E.Id FROM Events as E WHERE 1';
|
||||
$eventsSql .= $_SESSION['montageReviewFilter']['sql'];
|
||||
$results = dbQuery($eventsSql);
|
||||
$eids = [];
|
||||
while ( $event_row = dbFetchNext( $results ) ) {
|
||||
array_push($eids, 'eids[]='.$event_row['Id']);
|
||||
}
|
||||
$_REQUEST['eids'] = $eids;
|
||||
session_start();
|
||||
unset($_SESSION['montageReviewFilter']);
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
$focusWindow = true;
|
||||
|
||||
xhtmlHeaders(__FILE__, translate('Download') );
|
||||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div id="header">
|
||||
<div id="headerButtons">
|
||||
<a href="#" onclick="closeWindow()"><?php echo translate('Close') ?></a>
|
||||
</div>
|
||||
<h2><?php echo translate('Download') ?></h2>
|
||||
</div>
|
||||
<div id="content">
|
||||
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
|
||||
<?php
|
||||
if ( !empty($_REQUEST['eid']) ) {
|
||||
?>
|
||||
<input type="hidden" name="id" value="<?php echo validInt($_REQUEST['eid']) ?>"/>
|
||||
<?php
|
||||
} else if ( !empty($_REQUEST['eids']) ) {
|
||||
foreach ( $_REQUEST['eids'] as $eid ) {
|
||||
?>
|
||||
<input type="hidden" name="eids[]" value="<?php echo validInt($eid) ?>"/>
|
||||
<?php
|
||||
}
|
||||
unset( $eid );
|
||||
}
|
||||
?>
|
||||
<table id="contentTable" class="minor" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><input type="hidden" name="exportVideo" value="1"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><?php echo translate('ExportFormat') ?></th>
|
||||
<td>
|
||||
<input type="radio" id="exportFormatTar" name="exportFormat" value="tar" onclick="configureExportButton(this)"/>
|
||||
<label for="exportFormatTar"><?php echo translate('ExportFormatTar') ?></label>
|
||||
<input type="radio" id="exportFormatZip" name="exportFormat" value="zip" checked="checked" onclick="configureExportButton(this);"/>
|
||||
<label for="exportFormatZip"><?php echo translate('ExportFormatZip') ?></label>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<input type="button" id="exportButton" name="exportButton" value="<?php echo translate('GenerateDownload') ?>" onclick="exportEvent(this.form);" />
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
if ( isset($_REQUEST['generated']) ) {
|
||||
?>
|
||||
<h2 id="exportProgress" class="<?php echo $_REQUEST['generated']?'infoText':'errorText' ?>">
|
||||
<span id="exportProgressText"><?php echo $_REQUEST['generated']?translate('ExportSucceeded'):translate('ExportFailed') ?></span>
|
||||
<span id="exportProgressTicker"></span>
|
||||
</h2>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<h2 id="exportProgress" class="hidden warnText">
|
||||
<span id="exportProgressText"><?php echo translate('Exporting') ?></span>
|
||||
<span id="exportProgressTicker"></span>
|
||||
</h2>
|
||||
<?php
|
||||
}
|
||||
if ( !empty($_REQUEST['generated']) ) {
|
||||
?>
|
||||
<h3 id="downloadLink"><a href="<?php echo validHtmlStr($_REQUEST['exportFile']) ?>"><?php echo translate('Download') ?></a></h3>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -96,34 +96,27 @@ xhtmlHeaders(__FILE__, translate('Event') );
|
|||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div id="content">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<div id="header">
|
||||
<?php
|
||||
if ( ! $Event->Id() ) {
|
||||
echo 'Event was not found.';
|
||||
} else {
|
||||
?>
|
||||
<div id="dataBar">
|
||||
<table id="dataTable" class="major">
|
||||
<tr>
|
||||
<td><span id="dataId" title="<?php echo translate('Id') ?>"><?php echo $Event->Id() ?></span></td>
|
||||
<td><span id="dataCause" title="<?php echo $Event->Notes()?validHtmlStr($Event->Notes()):translate('AttrCause') ?>"><?php echo validHtmlStr($Event->Cause()) ?></span></td>
|
||||
<td><span id="dataTime" title="<?php echo translate('Time') ?>"><?php echo strftime( STRF_FMT_DATETIME_SHORT, strtotime($Event->StartTime() ) ) ?></span></td>
|
||||
<td><span id="dataDuration" title="<?php echo translate('Duration') ?>"><?php echo $Event->Length() ?></span>s</td>
|
||||
<td><span id="dataFrames" title="<?php echo translate('AttrFrames')."/".translate('AttrAlarmFrames') ?>"><?php echo $Event->Frames() ?>/<?php echo $Event->AlarmFrames() ?></span></td>
|
||||
<td><span id="dataScore" title="<?php echo translate('AttrTotalScore')."/".translate('AttrAvgScore')."/".translate('AttrMaxScore') ?>"><?php echo $Event->TotScore() ?>/<?php echo $Event->AvgScore() ?>/<?php echo $Event->MaxScore() ?></span></td>
|
||||
</tr>
|
||||
</table>
|
||||
<span id="dataId" title="<?php echo translate('Id') ?>"><?php echo $Event->Id() ?></span>
|
||||
<span id="dataCause" title="<?php echo $Event->Notes()?validHtmlStr($Event->Notes()):translate('AttrCause') ?>"><?php echo validHtmlStr($Event->Cause()) ?></span>
|
||||
<span id="dataTime" title="<?php echo translate('Time') ?>"><?php echo strftime( STRF_FMT_DATETIME_SHORT, strtotime($Event->StartTime() ) ) ?></span>
|
||||
<span id="dataDuration" title="<?php echo translate('Duration') ?>"><?php echo $Event->Length().'s' ?></span>
|
||||
<span id="dataFrames" title="<?php echo translate('AttrFrames')."/".translate('AttrAlarmFrames') ?>"><?php echo $Event->Frames() ?>/<?php echo $Event->AlarmFrames() ?></span>
|
||||
<span id="dataScore" title="<?php echo translate('AttrTotalScore')."/".translate('AttrAvgScore')."/".translate('AttrMaxScore') ?>"><?php echo $Event->TotScore() ?>/<?php echo $Event->AvgScore() ?>/<?php echo $Event->MaxScore() ?></span>
|
||||
<div id="closeWindow"><a href="#" onclick="window.history.back();"><?php echo translate('Back') ?></a></div>
|
||||
</div>
|
||||
<div id="menuBar1">
|
||||
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo buildSelect( "scale", $scales, "changeScale();" ); ?></div>
|
||||
<div id="replayControl"><label for="replayMode"><?php echo translate('Replay') ?></label><?php echo buildSelect( "replayMode", $replayModes, "changeReplayMode();" ); ?></div>
|
||||
<div id="nameControl">
|
||||
<input type="text" id="eventName" name="eventName" value="<?php echo validHtmlStr($Event->Name()) ?>" />
|
||||
<input type="button" value="<?php echo translate('Rename') ?>" onclick="renameEvent()"<?php if ( !canEdit( 'Events' ) ) { ?> disabled="disabled"<?php } ?>/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="menuBar2">
|
||||
<div id="closeWindow"><a href="#" onclick="closeWindow();"><?php echo translate('Close') ?></a></div>
|
||||
<?php
|
||||
if ( canEdit('Events') ) {
|
||||
?>
|
||||
|
@ -149,7 +142,11 @@ if ( canEdit('Events') ) {
|
|||
} // end if Event->DefaultVideo
|
||||
?>
|
||||
<div id="exportEvent"><a href="#" onclick="exportEvent();"><?php echo translate('Export') ?></a></div>
|
||||
<div id="replayControl"><label for="replayMode"><?php echo translate('Replay') ?></label><?php echo buildSelect( "replayMode", $replayModes, "changeReplayMode();" ); ?></div>
|
||||
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo buildSelect( "scale", $scales, "changeScale();" ); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div id="eventVideo" class="">
|
||||
<?php
|
||||
if ( $Event->DefaultVideo() ) {
|
||||
|
@ -180,7 +177,7 @@ Warning("Streamsrc: $streamSrc");
|
|||
}
|
||||
} // end if stream method
|
||||
?>
|
||||
<div id="alarmCue" class="alarmCue" style="width: <?php echo reScale($Event->Width(), $scale);?>px;"></div>
|
||||
<div id="alarmCue" class="alarmCue"></div>
|
||||
<div id="progressBar" style="width: <?php echo reScale($Event->Width(), $scale);?>px;">
|
||||
<div class="progressBox" id="progressBox" title="" style="width: 0%;"></div>
|
||||
</div><!--progressBar-->
|
||||
|
@ -220,6 +217,13 @@ Warning("Streamsrc: $streamSrc");
|
|||
</div>
|
||||
</div>
|
||||
<div id="eventImageNav">
|
||||
<div id="thumbsSliderPanel">
|
||||
<div id="alarmCue" class="alarmCue"></div>
|
||||
<div id="thumbsSlider">
|
||||
<div id="thumbsKnob">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="eventImageButtons">
|
||||
<div id="prevButtonsPanel">
|
||||
<input id="prevEventBtn" type="button" value="<E" onclick="prevEvent()" disabled="disabled"/>
|
||||
|
@ -230,12 +234,6 @@ Warning("Streamsrc: $streamSrc");
|
|||
<input id="nextEventBtn" type="button" value="E>" onclick="nextEvent()" disabled="disabled"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="thumbsSliderPanel">
|
||||
<div id="thumbsSlider">
|
||||
<div id="thumbsKnob">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
|
|
@ -81,10 +81,6 @@ if ( !empty($page) ) {
|
|||
$eventsSql .= ' limit 0, '.$limit;
|
||||
}
|
||||
|
||||
$maxWidth = 0;
|
||||
$maxHeight = 0;
|
||||
$archived = false;
|
||||
$unarchived = false;
|
||||
$maxShortcuts = 5;
|
||||
$pagination = getPagination( $pages, $page, $maxShortcuts, $filterQuery.$sortQuery.'&limit='.$limit );
|
||||
|
||||
|
@ -95,8 +91,20 @@ xhtmlHeaders(__FILE__, translate('Events') );
|
|||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<div id="header">
|
||||
<div id="headerButtons">
|
||||
<div id="info">
|
||||
<h2><?php echo sprintf( $CLANG['EventCount'], $nEvents, zmVlang( $VLANG['Event'], $nEvents ) ) ?></h2>
|
||||
<a id="refreshLink" href="#" onclick="location.reload(true);"><?php echo translate('Refresh') ?></a>
|
||||
</div>
|
||||
<div id="pagination">
|
||||
<?php
|
||||
if ( $pagination ) {
|
||||
?>
|
||||
<h2 class="pagination"><?php echo $pagination ?></h2>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
if ( $pages > 1 ) {
|
||||
if ( !empty($page) ) {
|
||||
|
@ -110,9 +118,11 @@ if ( $pages > 1 ) {
|
|||
}
|
||||
}
|
||||
?>
|
||||
<a href="#" onclick="closeWindows();"><?php echo translate('Close') ?></a>
|
||||
</div>
|
||||
<h2><?php echo sprintf( $CLANG['EventCount'], $nEvents, zmVlang( $VLANG['Event'], $nEvents ) ) ?></h2>
|
||||
<div id="controls">
|
||||
<a href="#" onclick="window.history.back();"><?php echo translate('Back') ?></a>
|
||||
<a id="timelineLink" href="?view=timeline<?php echo $filterQuery ?>"><?php echo translate('ShowTimeline') ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
<form name="contentForm" id="contentForm" method="post" action="">
|
||||
|
@ -123,18 +133,6 @@ if ( $pages > 1 ) {
|
|||
<input type="hidden" name="sort_field" value="<?php echo validHtmlStr($_REQUEST['sort_field']) ?>"/>
|
||||
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
|
||||
<input type="hidden" name="limit" value="<?php echo $limit ?>"/>
|
||||
<?php
|
||||
if ( $pagination ) {
|
||||
?>
|
||||
<h3 class="pagination"><?php echo $pagination ?></h3>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<p id="controls">
|
||||
<a id="refreshLink" href="#" onclick="location.reload(true);"><?php echo translate('Refresh') ?></a>
|
||||
<a id="filterLink" href="#" onclick="createPopup( '?view=filter&page=<?php echo $page ?><?php echo $filterQuery ?>', 'zmFilter', 'filter' );"><?php echo translate('ShowFilterWindow') ?></a>
|
||||
<a id="timelineLink" href="#" onclick="createPopup( '?view=timeline<?php echo $filterQuery ?>', 'zmTimeline', 'timeline' );"><?php echo translate('ShowTimeline') ?></a>
|
||||
</p>
|
||||
<table id="contentTable" class="major">
|
||||
<tbody>
|
||||
<?php
|
||||
|
@ -144,11 +142,6 @@ $disk_space_total = 0;
|
|||
$results = dbQuery( $eventsSql );
|
||||
while ( $event_row = dbFetchNext( $results ) ) {
|
||||
$event = new Event( $event_row );
|
||||
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
|
||||
$eventWidth = reScale( $event_row['Width'], $scale );
|
||||
$eventHeight = reScale( $event_row['Height'], $scale );
|
||||
if ( $maxWidth < $eventWidth ) $maxWidth = $eventWidth;
|
||||
if ( $maxHeight < $eventHeight ) $maxHeight = $eventHeight;
|
||||
if ( $event_row['Archived'] )
|
||||
$archived = true;
|
||||
else
|
||||
|
@ -187,8 +180,8 @@ while ( $event_row = dbFetchNext( $results ) ) {
|
|||
$scale = max( reScale( SCALE_BASE, $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
|
||||
?>
|
||||
<tr<?php if ($event->Archived()) echo ' class="archived"' ?>>
|
||||
<td class="colId"><?php echo makePopupLink( '?view=event&eid='.$event->Id().$filterQuery.$sortQuery.'&page=1', 'zmEvent', array( 'event', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $event->Id().($event->Archived()?'*':'') ) ?></td>
|
||||
<td class="colName"><?php echo makePopupLink( '?view=event&eid='.$event->Id().$filterQuery.$sortQuery.'&page=1', 'zmEvent', array( 'event', reScale( $event->Width(), $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ), reScale( $event->Height(), $event->DefaultScale(), ZM_WEB_DEFAULT_SCALE ) ), validHtmlStr($event->Name()).($event->Archived()?'*':'' ) ) ?></td>
|
||||
<td class="colId"><a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&page=1"> '.$event->Id().($event->Archived()?'*':'') ?></a></td>
|
||||
<td class="colName"><a href="?view=event&eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&page=1"> '.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a></td>
|
||||
<td class="colMonitorName"><?php echo makePopupLink( '?view=monitor&mid='.$event->MonitorId(), 'zmMonitor'.$event->Monitorid(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
|
||||
<td class="colCause"><?php echo makePopupLink( '?view=eventdetail&eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?></td>
|
||||
<td class="colTime"><?php echo strftime( STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime()) ) ?></td>
|
||||
|
@ -276,6 +269,7 @@ if ( true || canEdit( 'Events' ) ) {
|
|||
<input type="button" name="unarchiveBtn" value="<?php echo translate('Unarchive') ?>" onclick="unarchiveEvents( this, 'markEids' );" disabled="disabled"/>
|
||||
<input type="button" name="editBtn" value="<?php echo translate('Edit') ?>" onclick="editEvents( this, 'markEids' )" disabled="disabled"/>
|
||||
<input type="button" name="exportBtn" value="<?php echo translate('Export') ?>" onclick="exportEvents( this, 'markEids' )" disabled="disabled"/>
|
||||
<input type="button" name="downloadBtn" value="<?php echo translate('DownloadVideo') ?>" onclick="downloadVideo( this, 'markEids' )" disabled="disabled"/>
|
||||
<input type="button" name="deleteBtn" value="<?php echo translate('Delete') ?>" onclick="deleteEvents( this, 'markEids' );" disabled="disabled"/>
|
||||
</div>
|
||||
<?php
|
||||
|
@ -288,8 +282,6 @@ if ( true || canEdit( 'Events' ) ) {
|
|||
// These are defined in the .js.php but need to be updated down here.
|
||||
archivedEvents = <?php echo !empty($archived)?'true':'false' ?>;
|
||||
unarchivedEvents = <?php echo !empty($unarchived)?'true':'false' ?>;
|
||||
maxWidth = <?php echo $maxWidth?$maxWidth:0 ?>;
|
||||
maxHeight = <?php echo $maxHeight?$maxHeight:0 ?>;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -231,7 +231,7 @@ for ( $i = 0; $i < count($terms); $i++ ) {
|
|||
<?php
|
||||
} elseif ( $term['attr'] == 'MonitorName' ) {
|
||||
$monitors = array();
|
||||
foreach ( dbFetchAll( 'select Id,Name from Monitors order by Sequence asc' ) as $monitor ) {
|
||||
foreach ( dbFetchAll( 'select Id,Name from Monitors order by Name asc' ) as $monitor ) {
|
||||
if ( visibleMonitor( $monitor['Id'] ) ) {
|
||||
$monitors[$monitor['Name']] = $monitor['Name'];
|
||||
}
|
||||
|
@ -385,7 +385,11 @@ if ( ZM_OPT_MESSAGE ) {
|
|||
</p>
|
||||
<p>
|
||||
<label><?php echo translate('FilterDeleteEvents') ?></label>
|
||||
<input type="checkbox" name="filter[AutoDelete]" value="1"<?php if ( !empty($filter->AutoDelete()) ) { ?> checked="checked"<?php } ?> onclick="updateButtons( this )"/>
|
||||
<input type="checkbox" name="filter[AutoDelete]" value="1"<?php if ( !empty($filter->AutoDelete()) ) { ?> checked="checked"<?php } ?> onclick="updateButtons(this)"/>
|
||||
</p>
|
||||
<p><label><?php echo translate('FilterMoveEvents') ?></label>
|
||||
<input type="checkbox" name="filter[AutoMove]" value="1"<?php if ( !empty($filter->AutoMove()) ) { ?> checked="checked"<?php } ?> onclick="updateButtons(this);if(this.checked){$j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');}else{this.form.elements['filter[AutoMoveTo]'].hide();};"/>
|
||||
<?php echo htmlSelect( "filter[AutoMoveTo]", $storageareas, $filter->AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;' ) ); ?>
|
||||
</p>
|
||||
<p>
|
||||
<label for="background"><?php echo translate('BackgroundFilter') ?></label>
|
||||
|
|
|
@ -51,7 +51,7 @@ $lastFid = $maxFid;
|
|||
$alarmFrame = $Frame->Type()=='Alarm';
|
||||
|
||||
if ( isset( $_REQUEST['scale'] ) ) {
|
||||
$scale = validInt($_REQUEST['scale']);
|
||||
$scale = $_REQUEST['scale'];
|
||||
} else if ( isset( $_COOKIE['zmWatchScale'.$Monitor->Id()] ) ) {
|
||||
$scale = $_COOKIE['zmWatchScale'.$Monitor->Id()];
|
||||
} else if ( isset( $_COOKIE['zmWatchScale'] ) ) {
|
||||
|
|
|
@ -104,7 +104,7 @@ echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('o
|
|||
<select name="newGroup[MonitorIds][]" size="4" multiple="multiple" onchange="configureButtons(this);">
|
||||
<?php
|
||||
$monitors = dbFetchAll( 'SELECT Id,Name FROM Monitors ORDER BY Sequence ASC' );
|
||||
$monitorIds = array_flip( explode( ',', $newGroup->MonitorIds() ) );
|
||||
$monitorIds = $newGroup->MonitorIds();
|
||||
foreach ( $monitors as $monitor ) {
|
||||
if ( visibleMonitor( $monitor['Id'] ) ) {
|
||||
?>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
function startDownload( exportFile ) {
|
||||
window.location.replace( exportFile );
|
||||
}
|
||||
|
||||
var exportTimer = null;
|
||||
|
||||
function exportProgress() {
|
||||
var tickerText = $('exportProgressTicker').get('text');
|
||||
if ( tickerText.length < 1 || tickerText.length > 4 )
|
||||
$('exportProgressTicker').set( 'text', '.' );
|
||||
else
|
||||
$('exportProgressTicker').appendText( '.' );
|
||||
}
|
||||
|
||||
function exportResponse( respObj, respText ) {
|
||||
window.location.replace( thisUrl+'?view='+currentView+'&'+eidParm+'&exportFile='+respObj.exportFile+'&generated='+((respObj.result=='Ok')?1:0) );
|
||||
}
|
||||
|
||||
function exportEvent( form ) {
|
||||
var parms = 'view=request&request=event&action=download';
|
||||
parms += '&'+$(form).toQueryString();
|
||||
var query = new Request.JSON( { url: thisUrl, method: 'post', data: parms, onSuccess: exportResponse } );
|
||||
query.send();
|
||||
$('exportProgress').removeClass( 'hidden' );
|
||||
$('exportProgress').setProperty( 'class', 'warnText' );
|
||||
$('exportProgressText').set( 'text', exportProgressString );
|
||||
exportProgress();
|
||||
exportTimer = exportProgress.periodical( 500 );
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
if ( exportReady ) {
|
||||
startDownload.pass( exportFile ).delay( 1500 );
|
||||
}
|
||||
}
|
||||
|
||||
window.addEvent( 'domready', initPage );
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
if ( isset($_REQUEST['eids']) ) {
|
||||
$eidParms = array();
|
||||
foreach ( $_REQUEST['eids'] as $eid )
|
||||
$eidParms[] = "eids[]=".validInt($eid);
|
||||
?>
|
||||
var eidParm = '<?php echo join( '&', $eidParms ) ?>';
|
||||
<?php
|
||||
} else if (isset($_REQUEST['eid'])) {
|
||||
?>
|
||||
var eidParm = 'eid=<?php echo validInt($_REQUEST['eid']) ?>';
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
var exportReady = <?php echo !empty($_REQUEST['generated'])?'true':'false' ?>;
|
||||
var exportFile = '<?php echo !empty($_REQUEST['exportFile'])?validJsStr($_REQUEST['exportFile']):'' ?>';
|
||||
|
||||
var exportProgressString = '<?php echo addslashes(translate('Exporting')) ?>';
|
|
@ -40,8 +40,6 @@ function vjsReplay() {
|
|||
}
|
||||
}
|
||||
|
||||
$j.ajaxSetup ({timeout: AJAX_TIMEOUT }); //sets timeout for all getJSON.
|
||||
|
||||
var cueFrames = null; //make cueFrames availaible even if we don't send another ajax query
|
||||
|
||||
function initialAlarmCues (eventId) {
|
||||
|
@ -50,13 +48,13 @@ function initialAlarmCues (eventId) {
|
|||
|
||||
function setAlarmCues (data) {
|
||||
cueFrames = data.frames;
|
||||
alarmSpans = renderAlarmCues();
|
||||
alarmSpans = renderAlarmCues(vid ? $j("#videoobj") : $j("#evtStream"));//use videojs width or zms width
|
||||
$j(".alarmCue").html(alarmSpans);
|
||||
}
|
||||
|
||||
function renderAlarmCues () {
|
||||
function renderAlarmCues (containerEl) {
|
||||
if (cueFrames) {
|
||||
var cueRatio = (vid ? $j("#videoobj").width() : $j("#evtStream").width()) / (cueFrames[cueFrames.length - 1].Delta * 100);//use videojs width or zms width
|
||||
var cueRatio = containerEl.width() / (cueFrames[cueFrames.length - 1].Delta * 100);
|
||||
var minAlarm = Math.ceil(1/cueRatio);
|
||||
var spanTimeStart = 0;
|
||||
var spanTimeEnd = 0;
|
||||
|
@ -134,45 +132,21 @@ function setButtonState( element, butClass ) {
|
|||
}
|
||||
}
|
||||
|
||||
var resizeTimer;
|
||||
|
||||
function endOfResize(e) {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(changeScale, 250);
|
||||
}
|
||||
|
||||
function scaleToFit () {
|
||||
$j(window).on('resize', endOfResize) //set delayed scaling when Scale to Fit is selected
|
||||
let ratio = eventData.Width/eventData.Height;
|
||||
let container = $j('#content');
|
||||
let feed = $j(vid ? '#videoobj' : '#evtStream');
|
||||
let viewPort = $j(window);
|
||||
let newHeight = viewPort.height() - (container.outerHeight(true) - feed.outerHeight(true));
|
||||
let newWidth = ratio * newHeight;
|
||||
if (newWidth > container.innerWidth()) {
|
||||
newWidth = container.innerWidth();
|
||||
newHeight = newWidth / ratio;
|
||||
}
|
||||
let autoScale = Math.round(newWidth / eventData.Width * SCALE_BASE);
|
||||
let scales = $j('#scale option').map(function() {return parseInt($j(this).val());}).get();
|
||||
scales.shift();
|
||||
let closest = null;
|
||||
$j(scales).each(function () { //Set zms scale to nearest regular scale. Zoom does not like arbitrary scale values.
|
||||
if (closest == null || Math.abs(this - autoScale) < Math.abs(closest - autoScale)) {
|
||||
closest = this.valueOf();
|
||||
}
|
||||
});
|
||||
autoScale = closest;
|
||||
return {width: Math.floor(newWidth), height: Math.floor(newHeight), autoScale: autoScale};
|
||||
}
|
||||
|
||||
function changeScale() {
|
||||
let scale = $j('#scale').val();
|
||||
let newWidth = null;
|
||||
let newHeight = null;
|
||||
let autoScale = null;
|
||||
let newWidth;
|
||||
let newHeight;
|
||||
let autoScale;
|
||||
let eventViewer;
|
||||
let alarmCue = $j('div.alarmCue');
|
||||
let bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus');
|
||||
if (streamMode == 'stills') {
|
||||
eventViewer = $j('#eventThumbs');
|
||||
} else {
|
||||
eventViewer = $j(vid ? '#videoobj' : '#evtStream');
|
||||
}
|
||||
if (scale == "auto") {
|
||||
let newSize = scaleToFit();
|
||||
let newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl);
|
||||
newWidth = newSize.width;
|
||||
newHeight = newSize.height;
|
||||
autoScale = newSize.autoScale;
|
||||
|
@ -181,16 +155,18 @@ function changeScale() {
|
|||
newWidth = eventData.Width * scale / SCALE_BASE;
|
||||
newHeight = eventData.Height * scale / SCALE_BASE;
|
||||
}
|
||||
let alarmCue = $j('div.alarmCue');
|
||||
let eventViewer = $j(vid ? '#videoobj' : '#evtStream')
|
||||
eventViewer.width(newWidth);
|
||||
if (!(streamMode == 'stills')) eventViewer.width(newWidth); //stills handles its own width
|
||||
eventViewer.height(newHeight);
|
||||
if ( !vid ) { // zms needs extra sizing
|
||||
streamScale(scale == "auto" ? autoScale : scale);
|
||||
alarmCue.width(newWidth);
|
||||
drawProgressBar();
|
||||
}
|
||||
alarmCue.html(renderAlarmCues());//just re-render alarmCues. skip ajax call
|
||||
if (streamMode == 'stills') {
|
||||
slider.autosize();
|
||||
alarmCue.html(renderAlarmCues($j('#thumbsSliderPanel')));
|
||||
} else {
|
||||
alarmCue.html(renderAlarmCues(eventViewer));//just re-render alarmCues. skip ajax call
|
||||
}
|
||||
if (scale == "auto") {
|
||||
Cookie.write('zmEventScaleAuto', 'auto', {duration: 10*365});
|
||||
}else{
|
||||
|
@ -505,6 +481,7 @@ function streamQuery() {
|
|||
|
||||
var slider = null;
|
||||
var scroll = null;
|
||||
var currEventId = null;
|
||||
var CurEventDefVideoPath = null;
|
||||
|
||||
function getEventResponse( respObj, respText ) {
|
||||
|
@ -698,13 +675,11 @@ function resetEventStills() {
|
|||
fid = 1;
|
||||
else if ( fid > eventData.Frames )
|
||||
fid = eventData.Frames;
|
||||
checkFrames( eventData.Id, fid );
|
||||
checkFrames( eventData.Id, fid, ($j('#eventImagePanel').css('display')=='none'?'':'true'));
|
||||
scroll.toElement( 'eventThumb'+fid );
|
||||
}
|
||||
} ).set( 0 );
|
||||
}
|
||||
if ( $('eventThumbs').getStyle( 'height' ).match( /^\d+/ ) < (parseInt(eventData.Height)+80) )
|
||||
$('eventThumbs').setStyle( 'height', ($j(vid ? '#videoobj' : '#evtStream').height())+'px' );
|
||||
}
|
||||
|
||||
function getFrameResponse( respObj, respText ) {
|
||||
|
@ -837,10 +812,6 @@ function getActResponse( respObj, respText ) {
|
|||
if ( checkStreamForErrors( "getActResponse", respObj ) )
|
||||
return;
|
||||
|
||||
if ( respObj.refreshParent )
|
||||
if (refreshParent == false) refreshParent = true; //Bypass filter window redirect fix.
|
||||
refreshParentWindow();
|
||||
|
||||
if ( respObj.refreshEvent )
|
||||
eventQuery( eventData.Id );
|
||||
}
|
||||
|
@ -893,6 +864,7 @@ function showStream() {
|
|||
$('streamEvent').addClass( 'hidden' );
|
||||
|
||||
streamMode = 'video';
|
||||
if (scale == 'auto') changeScale();
|
||||
}
|
||||
|
||||
function showStills() {
|
||||
|
@ -924,6 +896,7 @@ function showStills() {
|
|||
);
|
||||
}
|
||||
resetEventStills();
|
||||
if (scale == 'auto') changeScale();
|
||||
}
|
||||
|
||||
function showFrameStats() {
|
||||
|
|
|
@ -48,6 +48,7 @@ var canEditEvents = <?php echo canEdit( 'Events' )?'true':'false' ?>;
|
|||
var streamTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||
|
||||
var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
|
||||
var streamMode = '<?php echo $streamMode ?>';
|
||||
|
||||
//
|
||||
// Strings
|
||||
|
|
|
@ -15,6 +15,7 @@ function toggleCheckbox( element, name ) {
|
|||
form.editBtn.disabled = !checked;
|
||||
form.archiveBtn.disabled = unarchivedEvents?!checked:true;
|
||||
form.unarchiveBtn.disabled = archivedEvents?!checked:true;
|
||||
form.downloadBtn.disabled = !checked;
|
||||
form.exportBtn.disabled = !checked;
|
||||
form.deleteBtn.disabled = !checked;
|
||||
}
|
||||
|
@ -38,6 +39,7 @@ function configureButton( element, name ) {
|
|||
form.editBtn.disabled = !checked;
|
||||
form.archiveBtn.disabled = (!checked)||(!unarchivedEvents);
|
||||
form.unarchiveBtn.disabled = (!checked)||(!archivedEvents);
|
||||
form.downloadBtn.disabled = !checked;
|
||||
form.exportBtn.disabled = !checked;
|
||||
form.deleteBtn.disabled = !checked;
|
||||
}
|
||||
|
@ -74,6 +76,19 @@ function editEvents( element, name ) {
|
|||
createPopup( '?view=eventdetail&'+eids.join( '&' ), 'zmEventDetail', 'eventdetail' );
|
||||
}
|
||||
|
||||
function downloadVideo( element, name ) {
|
||||
var form = element.form;
|
||||
var eids = new Array();
|
||||
for (var i = 0; i < form.elements.length; i++) {
|
||||
if (form.elements[i].name.indexOf(name) == 0) {
|
||||
if ( form.elements[i].checked ) {
|
||||
eids[eids.length] = 'eids[]='+form.elements[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
createPopup( '?view=download&'+eids.join( '&' ), 'zmDownload', 'download' );
|
||||
}
|
||||
|
||||
function exportEvents( element, name ) {
|
||||
var form = element.form;
|
||||
var eids = new Array();
|
||||
|
|
|
@ -4,10 +4,7 @@ var openFilterWindow = false;
|
|||
var archivedEvents = <?php echo !empty($archived)?'true':'false' ?>;
|
||||
var unarchivedEvents = <?php echo !empty($unarchived)?'true':'false' ?>;
|
||||
|
||||
var filterQuery = '<?php echo isset($filterQuery)?validJsStr($filterQuery):'' ?>';
|
||||
var sortQuery = '<?php echo isset($sortQuery)?validJsStr($sortQuery):'' ?>';
|
||||
|
||||
var maxWidth = <?php echo $maxWidth?$maxWidth:0 ?>;
|
||||
var maxHeight = <?php echo $maxHeight?$maxHeight:0 ?>;
|
||||
var filterQuery = '<?php echo isset($filterQuery)?validJsStr(htmlspecialchars_decode($filterQuery)):'' ?>';
|
||||
var sortQuery = '<?php echo isset($sortQuery)?validJsStr(htmlspecialchars_decode($sortQuery)):'' ?>';
|
||||
|
||||
var confirmDeleteEventsString = "<?php echo addslashes(translate('ConfirmDeleteEvents')) ?>";
|
||||
|
|
|
@ -49,7 +49,6 @@ function submitToFilter( element ) {
|
|||
function submitToEvents( element ) {
|
||||
var form = element.form;
|
||||
if ( validateForm( form ) ) {
|
||||
form.target = 'zmEvents';
|
||||
form.action = thisUrl + '?view=events';
|
||||
form.submit();
|
||||
}
|
||||
|
@ -58,7 +57,6 @@ function submitToEvents( element ) {
|
|||
function executeFilter( element ) {
|
||||
var form = element.form;
|
||||
if ( validateForm( form ) ) {
|
||||
form.target = 'zmEvents';
|
||||
form.action = thisUrl + '?view=events';
|
||||
form.elements['action'].value = 'execute';
|
||||
form.submit();
|
||||
|
@ -67,8 +65,6 @@ function executeFilter( element ) {
|
|||
|
||||
function saveFilter( element ) {
|
||||
var form = element.form;
|
||||
|
||||
//form.target = 'zmFilter';
|
||||
form.target = window.name;
|
||||
form.elements['action'].value = element.value;
|
||||
form.action = thisUrl + '?view=filter';
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
var filterQuery = '<?php echo isset($filterQuery)?validJsStr(htmlspecialchars_decode($filterQuery)):'' ?>';
|
||||
var sortQuery = '<?php echo isset($sortQuery)?validJsStr(htmlspecialchars_decode($sortQuery)):'' ?>';
|
||||
|
||||
var deleteSavedFilterString = "<?php echo translate('DeleteSavedFilter') ?>";
|
||||
function validateForm( form ) {
|
||||
<?php
|
||||
|
|
|
@ -1,15 +1,35 @@
|
|||
function changeScale() {
|
||||
var scale = $('scale').get('value');
|
||||
var img = $('frameImg');
|
||||
if ( img ) {
|
||||
var baseWidth = $('base_width').value;
|
||||
var baseHeight = $('base_height').value;
|
||||
var newWidth = ( baseWidth * scale ) / SCALE_BASE;
|
||||
var newHeight = ( baseHeight * scale ) / SCALE_BASE;
|
||||
let scale = $j('#scale').val();
|
||||
let img = $j('#frameImg');
|
||||
let controlsLinks = {
|
||||
next: $j('#nextLink'),
|
||||
prev: $j('#prevLink'),
|
||||
first: $j('#firstLink'),
|
||||
last: $j('#lastLink')
|
||||
}
|
||||
|
||||
img.style.width = newWidth + "px";
|
||||
img.style.height = newHeight + "px";
|
||||
if (img) {
|
||||
let baseWidth = $j('#base_width').val();
|
||||
let baseHeight = $j('#base_height').val();
|
||||
if (scale == "auto") {
|
||||
let newSize = scaleToFit(baseWidth, baseHeight, img, $j('#controls'));
|
||||
newWidth = newSize.width;
|
||||
newHeight = newSize.height;
|
||||
autoScale = newSize.autoScale;
|
||||
} else {
|
||||
$j(window).off('resize', endOfResize); //remove resize handler when Scale to Fit is not active
|
||||
newWidth = baseWidth * scale / SCALE_BASE;
|
||||
newHeight = baseHeight * scale / SCALE_BASE;
|
||||
}
|
||||
img.css('width', newWidth + "px");
|
||||
img.css('height', newHeight + "px");
|
||||
}
|
||||
Cookie.write( 'zmWatchScale', scale, { duration: 10*365 } );
|
||||
$j.each(controlsLinks, function(k, anchor) { //Make frames respect scale choices
|
||||
anchor.prop('href', anchor.prop('href').replace(/scale=.*&/, 'scale=' + scale + '&'));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
if (scale == "auto") $j(document).ready(changeScale);
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
var scale = "<?php echo $scale ?>";
|
||||
|
||||
var SCALE_BASE = <?php echo SCALE_BASE ?>;
|
||||
|
|
|
@ -42,7 +42,7 @@ function evaluateLoadTimes() {
|
|||
imageLoadTimesEvaluated=0;
|
||||
setSpeed(speedIndex);
|
||||
$('fps').innerHTML="Display refresh rate is " + (1000 / currentDisplayInterval).toFixed(1) + " per second, avgFrac=" + avgFrac.toFixed(3) + ".";
|
||||
}
|
||||
} // end evaluateLoadTimes()
|
||||
|
||||
// time is seconds since epoch
|
||||
function SetImageSource( monId, time ) {
|
||||
|
@ -335,6 +335,7 @@ function redrawScreen() {
|
|||
$('zoomout').style.display="none";
|
||||
$('panleft').style.display="none";
|
||||
$('panright').style.display="none";
|
||||
if ($('downloadVideo')) $('downloadVideo').style.display="none";
|
||||
|
||||
} else {
|
||||
// switch out of liveview mode
|
||||
|
@ -351,6 +352,7 @@ function redrawScreen() {
|
|||
$('panleft').style.display="inline-flex";
|
||||
$('panright').style.display="inline";
|
||||
$('panright').style.display="inline-flex";
|
||||
if ($('downloadVideo')) $('downloadVideo').style.display="inline";
|
||||
}
|
||||
|
||||
if ( fitMode == 1 ) {
|
||||
|
@ -465,12 +467,12 @@ function setSpeed( speed_index ) {
|
|||
playSecsperInterval = Math.floor( 1000 * currentSpeed * currentDisplayInterval ) / 1000000;
|
||||
console.log("playSecsPerInterval: " + playSecsperInterval + " = currentspeed:" + currentSpeed + " * " + currentDisplayInterval + " /1000");
|
||||
showSpeed(speed_index);
|
||||
if ( timerInterval != currentDisplayInterval || currentSpeed == 0 ) timerFire(); // if the timer isn't firing we need to trigger it to update
|
||||
if ( timerInterval != currentDisplayInterval || currentSpeed == 0 ) timerFire(); // if the timer isn't firing we need to trigger it to update
|
||||
}
|
||||
|
||||
function setLive(value) {
|
||||
liveMode = value;
|
||||
redrawScreen();
|
||||
changeDateTime();
|
||||
}
|
||||
|
||||
|
||||
|
@ -510,16 +512,12 @@ function clicknav(minSecs,maxSecs,live) {// we use the current time if we can
|
|||
if ( live == 1 )
|
||||
liveStr="&live=1";
|
||||
|
||||
var fitStr="&fit=0";
|
||||
if ( fitMode == 1 )
|
||||
fitStr="&fit=1";
|
||||
|
||||
var zoomStr="";
|
||||
for ( var i=0; i < numMonitors; i++ )
|
||||
if ( monitorZoomScale[monitorPtr[i]] < 0.99 || monitorZoomScale[monitorPtr[i]] > 1.01 ) // allow for some up/down changes and just treat as 1 of almost 1
|
||||
zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2);
|
||||
|
||||
var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value];
|
||||
var uri = "?view=" + currentView + '&fit='+(fitMode==1?'1':'0') + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value];
|
||||
window.location = uri;
|
||||
} // end function clicknav
|
||||
|
||||
|
@ -557,6 +555,9 @@ function click_panright() {
|
|||
maxTimeSecs = minTimeSecs + rangeTimeSecs - 1;
|
||||
clicknav(minTimeSecs,maxTimeSecs,0);
|
||||
}
|
||||
function click_download() {
|
||||
createPopup( '?view=download', 'zmDownload', 'download' );
|
||||
}
|
||||
function click_all_events() {
|
||||
clicknav(0,0,0);
|
||||
}
|
||||
|
|
|
@ -31,14 +31,18 @@ var groupStr=<?php echo $group_id ? "'&group=$group_id'" : '""'; ?>;
|
|||
|
||||
// Because we might not have time as the criteria, figure out the min/max time when we run the query
|
||||
|
||||
$minTimeSecs = strtotime('2036-01-01 01:01:01');
|
||||
$maxTimeSecs = strtotime('1950-01-01 01:01:01');
|
||||
if ( ! $maxTimeSecs )
|
||||
$maxTimeSecs = time();
|
||||
if ( ! $minTimeSecs )
|
||||
$minTimeSecs = strtotime('2010-01-01 01:01:01');
|
||||
|
||||
// This builds the list of events that are eligible from this range
|
||||
|
||||
$index = 0;
|
||||
$anyAlarms = false;
|
||||
|
||||
if ( ! $initialModeIsLive ) {
|
||||
|
||||
$result = dbQuery( $eventsSql );
|
||||
if ( ! $result ) {
|
||||
Fatal('SQL-ERR');
|
||||
|
@ -81,6 +85,7 @@ if ( !isset($minTime) || !isset($maxTime) ) {
|
|||
$minTime = strftime($minTimeSecs);
|
||||
} else {
|
||||
$minTimeSecs = strtotime($minTime);
|
||||
|
||||
$maxTimeSecs = strtotime($maxTime);
|
||||
}
|
||||
|
||||
|
@ -136,6 +141,7 @@ if ( $mId > 0 ) {
|
|||
}
|
||||
|
||||
echo "var maxScore=$maxScore;\n"; // used to skip frame load if we find no alarms.
|
||||
} // end if initialmodeislive
|
||||
echo "var monitorName = [];\n";
|
||||
echo "var monitorLoading = [];\n";
|
||||
echo "var monitorImageObject = [];\n";
|
||||
|
|
|
@ -3,8 +3,7 @@ var events = {};
|
|||
function showEvent( eid, fid, width, height ) {
|
||||
var url = '?view=event&eid='+eid+'&fid='+fid;
|
||||
url += filterQuery;
|
||||
var pop=createPopup( url, 'zmEvent', 'event', width, height );
|
||||
pop.vid=$('preview');
|
||||
window.location.href = url;
|
||||
|
||||
//video element is blocking video elements elsewhere in chrome possible interaction with mouseover event?
|
||||
//FIXME unless an exact cause can be determined should store all video controls and do something to the other controls when we want to load a new video seek etc or whatever may block
|
||||
|
@ -144,13 +143,13 @@ function loadEventImage( imagePath, eid, fid, width, height, fps, videoName, dur
|
|||
|
||||
function tlZoomBounds( minTime, maxTime ) {
|
||||
console.log( "Zooming" );
|
||||
window.location = '?view='+currentView+filterQuery+'&minTime='+minTime+'&maxTime='+maxTime;
|
||||
location.replace('?view='+currentView+filterQuery+'&minTime='+minTime+'&maxTime='+maxTime);
|
||||
}
|
||||
|
||||
function tlZoomRange( midTime, range ) {
|
||||
window.location = '?view='+currentView+filterQuery+'&midTime='+midTime+'&range='+range;
|
||||
location.replace('?view='+currentView+filterQuery+'&midTime='+midTime+'&range='+range);
|
||||
}
|
||||
|
||||
function tlPan( midTime, range ) {
|
||||
window.location = '?view='+currentView+filterQuery+'&midTime='+midTime+'&range='+range;
|
||||
location.replace('?view='+currentView+filterQuery+'&midTime='+midTime+'&range='+range);
|
||||
}
|
||||
|
|
|
@ -25,8 +25,19 @@ function showPtzControls() {
|
|||
|
||||
function changeScale() {
|
||||
var scale = $('scale').get('value');
|
||||
var newWidth = ( monitorWidth * scale ) / SCALE_BASE;
|
||||
var newHeight = ( monitorHeight * scale ) / SCALE_BASE;
|
||||
var newWidth;
|
||||
var newHeight;
|
||||
if (scale == "auto") {
|
||||
let newSize = scaleToFit(monitorWidth, monitorHeight, $j('#liveStream'+monitorId), $j('#replayStatus'));
|
||||
newWidth = newSize.width;
|
||||
newHeight = newSize.height;
|
||||
autoScale = newSize.autoScale;
|
||||
} else {
|
||||
$j(window).off('resize', endOfResize); //remove resize handler when Scale to Fit is not active
|
||||
newWidth = monitorWidth * scale / SCALE_BASE;
|
||||
newHeight = monitorHeight * scale / SCALE_BASE;
|
||||
}
|
||||
|
||||
|
||||
Cookie.write( 'zmWatchScale'+monitorId, scale, { duration: 10*365 } );
|
||||
|
||||
|
@ -36,7 +47,7 @@ function changeScale() {
|
|||
streamImg.style.width = newWidth + "px";
|
||||
streamImg.style.height = newHeight + "px";
|
||||
|
||||
streamImg.src = streamImg.src.replace(/scale=\d+/i, 'scale='+scale);
|
||||
streamImg.src = streamImg.src.replace(/scale=\d+/i, 'scale='+(scale== 'auto' ? autoScale : scale));
|
||||
} else {
|
||||
console.error("No element found for liveStream.");
|
||||
}
|
||||
|
@ -655,6 +666,7 @@ function initPage() {
|
|||
|
||||
if ( refreshApplet && appletRefreshTime )
|
||||
appletRefresh.delay( appletRefreshTime*1000 );
|
||||
if (scale == "auto") changeScale();
|
||||
}
|
||||
|
||||
// Kick everything off
|
||||
|
|
|
@ -50,7 +50,7 @@ var monitorWidth = <?php echo $monitor->Width() ?>;
|
|||
var monitorHeight = <?php echo $monitor->Height() ?>;
|
||||
var monitorUrl = '<?php echo ( $monitor->Server()->Url() ) ?>';
|
||||
|
||||
var scale = <?php echo $scale ?>;
|
||||
var scale = '<?php echo $scale ?>';
|
||||
|
||||
var statusRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_STATUS ?>;
|
||||
var eventsRefreshTimeout = <?php echo 1000*ZM_WEB_REFRESH_EVENTS ?>;
|
||||
|
|
|
@ -78,7 +78,7 @@ if ( isset($_COOKIE['zmMontageLayout']) ) {
|
|||
$options = array();
|
||||
$Layout = '';
|
||||
$Positions = '';
|
||||
if ( $layout_id ) {
|
||||
if ( $layout_id and is_numeric($layout_id) and isset($layoutsById[$layout_id]) ) {
|
||||
$Layout = $layoutsById[$layout_id];
|
||||
$Positions = json_decode( $Layout->Positions(), true );
|
||||
}
|
||||
|
|
|
@ -59,6 +59,35 @@ include('_monitor_filters.php');
|
|||
$filter_bar = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($displayMonitors) != 0) {
|
||||
$filter = array(
|
||||
'Query' => array(
|
||||
'terms' => array(
|
||||
array('attr' => 'StartDateTime', 'op' => '>=', 'val' => $_REQUEST['minTime'], 'obr' => '1'),
|
||||
array('attr' => 'StartDateTime', 'op' => '<=', 'val' => $_REQUEST['maxTime'], 'cnj' => 'and', 'cbr' => '1'),
|
||||
)
|
||||
),
|
||||
);
|
||||
if (isset($_SESSION['MonitorId'])) {
|
||||
$filter['Query']['terms'][] = (array('attr' => 'MonitorId', 'op' => '=', 'val' => $_SESSION['MonitorId'], 'cnj' => 'and'));
|
||||
}
|
||||
if (( $group_id != 0 || isset($_SESSION['ServerFilter']) || isset($_SESSION['StorageFilter']) || isset($_SESSION['StatusFilter']) ) && !isset($_SESSION['MonitorId'])) {
|
||||
for ($i=0; $i < count($displayMonitors); $i++) {
|
||||
if ($i == '0') {
|
||||
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'and', 'obr' => '1');
|
||||
} else if ($i == (count($displayMonitors)-1)) {
|
||||
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or', 'cbr' => '1');
|
||||
} else {
|
||||
$filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or');
|
||||
}
|
||||
}
|
||||
}
|
||||
parseFilter( $filter );
|
||||
session_start();
|
||||
$_SESSION['montageReviewFilter'] = $filter;
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
// Note that this finds incomplete events as well, and any frame records written, but still cannot "see" to the end frame
|
||||
// if the bulk record has not been written - to be able to include more current frames reduce bulk frame sizes (event size can be large)
|
||||
// Note we round up just a bit on the end time as otherwise you get gaps, like 59.78 to 00 in the next second, which can give blank frames when moved through slowly.
|
||||
|
@ -106,6 +135,7 @@ if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) {
|
|||
$time = time();
|
||||
$maxTime = strftime("%FT%T",$time);
|
||||
$minTime = strftime("%FT%T",$time - 3600);
|
||||
Logger::Debug("Defaulting to $minTime to $maxTime");
|
||||
}
|
||||
if ( isset($_REQUEST['minTime']) )
|
||||
$minTime = validHtmlStr($_REQUEST['minTime']);
|
||||
|
@ -113,7 +143,7 @@ if ( isset($_REQUEST['minTime']) )
|
|||
if ( isset($_REQUEST['maxTime']) )
|
||||
$maxTime = validHtmlStr($_REQUEST['maxTime']);
|
||||
|
||||
// AS a special case a "all" is passed in as an exterme interval - if so , clear them here and let the database query find them
|
||||
// AS a special case a "all" is passed in as an extreme interval - if so, clear them here and let the database query find them
|
||||
|
||||
if ( (strtotime($maxTime) - strtotime($minTime))/(365*24*3600) > 30 ) {
|
||||
// test years
|
||||
|
@ -161,6 +191,7 @@ $eventsSql .= ' GROUP BY E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E.
|
|||
if ( isset($minTime) && isset($maxTime) ) {
|
||||
$minTimeSecs = strtotime($minTime);
|
||||
$maxTimeSecs = strtotime($maxTime);
|
||||
Logger::Debug("Min/max time secs: $minTimeSecs $maxTimeSecs");
|
||||
$eventsSql .= " HAVING CalcEndTimeSecs > '" . $minTimeSecs . "' AND StartTimeSecs < '" . $maxTimeSecs . "'";
|
||||
$frameSql .= " AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'";
|
||||
}
|
||||
|
@ -190,31 +221,38 @@ xhtmlHeaders(__FILE__, translate('MontageReview') );
|
|||
<input type="datetime-local" name="maxTime" id="maxTime" value="<?php echo preg_replace('/ /', 'T', $maxTime ) ?>" onchange="changeDateTime(this);">
|
||||
</div>
|
||||
<div id="ScaleDiv">
|
||||
<label for="scaleslider"><?php echo translate('Scale')?></label>
|
||||
<input id="scaleslider" type="range" min="0.1" max="1.0" value="<?php echo $defaultScale ?>" step="0.10" onchange="setScale(this.value);" oninput="showScale(this.value);"/>
|
||||
<span id="scaleslideroutput"><?php echo number_format((float)$defaultScale,2,'.','')?> x</span>
|
||||
<label for="scaleslider"><?php echo translate('Scale')?></label>
|
||||
<input id="scaleslider" type="range" min="0.1" max="1.0" value="<?php echo $defaultScale ?>" step="0.10" onchange="setScale(this.value);" oninput="showScale(this.value);"/>
|
||||
<span id="scaleslideroutput"><?php echo number_format((float)$defaultScale,2,'.','')?> x</span>
|
||||
</div>
|
||||
<div id="SpeedDiv">
|
||||
<label for="speedslider"><?php echo translate('Speed') ?></label>
|
||||
<input id="speedslider" type="range" min="0" max="<?php echo count($speeds)-1?>" value="<?php echo $speedIndex ?>" step="1" onchange="setSpeed(this.value);" oninput="showSpeed(this.value);"/>
|
||||
<span id="speedslideroutput"><?php echo $speeds[$speedIndex] ?> fps</span>
|
||||
<label for="speedslider"><?php echo translate('Speed') ?></label>
|
||||
<input id="speedslider" type="range" min="0" max="<?php echo count($speeds)-1?>" value="<?php echo $speedIndex ?>" step="1" onchange="setSpeed(this.value);" oninput="showSpeed(this.value);"/>
|
||||
<span id="speedslideroutput"><?php echo $speeds[$speedIndex] ?> fps</span>
|
||||
</div>
|
||||
<div style="display: inline-flex; border: 1px solid black; flex-flow: row wrap;">
|
||||
<button type="button" id="panleft" onclick="click_panleft();" >< <?php echo translate('Pan') ?></button>
|
||||
<button type="button" id="zoomin" onclick="click_zoomin();" ><?php echo translate('In +') ?></button>
|
||||
<button type="button" id="zoomout" onclick="click_zoomout();" ><?php echo translate('Out -') ?></button>
|
||||
<button type="button" id="lasteight" onclick="click_lastEight();" ><?php echo translate('8 Hour') ?></button>
|
||||
<button type="button" id="lasthour" onclick="click_lastHour();" ><?php echo translate('1 Hour') ?></button>
|
||||
<button type="button" id="allof" onclick="click_all_events();" ><?php echo translate('All Events') ?></button>
|
||||
<button type="button" id="live" onclick="setLive(1-liveMode);"><?php echo translate('Live') ?></button>
|
||||
<button type="button" id="fit" onclick="setFit(1-fitMode);" ><?php echo translate('Fit') ?></button>
|
||||
<button type="button" id="panright" onclick="click_panright();" ><?php echo translate('Pan') ?> ></button>
|
||||
<button type="button" id="panleft" onclick="click_panleft();" >< <?php echo translate('Pan') ?></button>
|
||||
<button type="button" id="zoomin" onclick="click_zoomin();" ><?php echo translate('In +') ?></button>
|
||||
<button type="button" id="zoomout" onclick="click_zoomout();" ><?php echo translate('Out -') ?></button>
|
||||
<button type="button" id="lasteight" onclick="click_lastEight();" ><?php echo translate('8 Hour') ?></button>
|
||||
<button type="button" id="lasthour" onclick="click_lastHour();" ><?php echo translate('1 Hour') ?></button>
|
||||
<button type="button" id="allof" onclick="click_all_events();" ><?php echo translate('All Events') ?></button>
|
||||
<button type="button" id="live" onclick="setLive(1-liveMode);"><?php echo translate('Live') ?></button>
|
||||
<button type="button" id="fit" onclick="setFit(1-fitMode);" ><?php echo translate('Fit') ?></button>
|
||||
<button type="button" id="panright" onclick="click_panright();" ><?php echo translate('Pan') ?> ></button>
|
||||
<?php
|
||||
if (count($displayMonitors) != 0) {
|
||||
?>
|
||||
<button type="button" id="downloadVideo" onclick="click_download();"><?php echo translate('Download Video') ?></button>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div id="timelinediv">
|
||||
<canvas id="timeline" onmousemove="mmove(event);" ontouchmove="tmove(event);" onmousedown="mdown(event);" onmouseup="mup(event);" onmouseout="mout(event);"></canvas>
|
||||
<span id="scrubleft"></span>
|
||||
<span id="scrubright"></span>
|
||||
<span id="scruboutput"></span>
|
||||
<canvas id="timeline" onmousemove="mmove(event);" ontouchmove="tmove(event);" onmousedown="mdown(event);" onmouseup="mup(event);" onmouseout="mout(event);"></canvas>
|
||||
<span id="scrubleft"></span>
|
||||
<span id="scrubright"></span>
|
||||
<span id="scruboutput"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -700,12 +700,16 @@ xhtmlHeaders(__FILE__, translate('Timeline') );
|
|||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<div id="header">
|
||||
<div id="headerButtons">
|
||||
<?php echo makePopupLink( '?view=events&page=1'.htmlspecialchars($filterQuery), 'zmEvents', 'events', translate('List'), canView( 'Events' ) ) ?>
|
||||
<a href="#" onclick="closeWindow();"><?php echo translate('Close') ?></a>
|
||||
<div id="info">
|
||||
<h2><?php echo translate('Timeline') ?></h2>
|
||||
<a id="refreshLink" href="#" onclick="location.reload(true);"><?php echo translate('Refresh') ?></a>
|
||||
</div>
|
||||
<div id="headerButtons">
|
||||
<a href="#" onclick="window.history.back();"><?php echo translate('Back') ?></a>
|
||||
<a href="?view=events&page=1<?php echo htmlspecialchars($filterQuery) ?>"><?php echo translate('List') ?></a>
|
||||
</div>
|
||||
<h2><?php echo translate('Timeline') ?></h2>
|
||||
</div>
|
||||
<div id="content" class="chartSize">
|
||||
<div id="topPanel" class="graphWidth">
|
||||
|
|
|
@ -61,14 +61,9 @@ xhtmlHeaders( __FILE__, $monitor->Name()." - ".translate('Feed') );
|
|||
?>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div id="content">
|
||||
<div id="menuBar">
|
||||
<?php echo getNavBarHTML() ?>
|
||||
<div id="header">
|
||||
<div id="monitorName"><?php echo $monitor->Name() ?></div>
|
||||
<script type="text/javascript">
|
||||
if ( window.opener ) {
|
||||
document.write('<div id="closeControl"><a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a></div>');
|
||||
}
|
||||
</script>
|
||||
<div id="menuControls">
|
||||
<?php
|
||||
if ( canView( 'Control' ) && $monitor->Type() == 'Local' ) {
|
||||
|
@ -79,7 +74,9 @@ if ( canView( 'Control' ) && $monitor->Type() == 'Local' ) {
|
|||
?>
|
||||
<div id="scaleControl"><?php echo translate('Scale') ?>: <?php echo buildSelect( "scale", $scales, "changeScale( this );" ); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="closeControl"><a href="#" onclick="window.history.back()"><?php echo translate('Back') ?></a></div>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div id="imageFeed"><?php echo getStreamHTML( $monitor, array('scale'=>$scale) ); ?></div>
|
||||
<div id="monitorStatus">
|
||||
<?php if ( canEdit( 'Monitors' ) ) { ?>
|
||||
|
|
|
@ -47,6 +47,7 @@ if ( $archivetype ) {
|
|||
if ( is_readable($filename_path) ) {
|
||||
header( "Content-type: application/$mimetype" );
|
||||
header( "Content-Disposition: attachment; filename=$filename");
|
||||
set_time_limit(0);
|
||||
readfile( $filename_path );
|
||||
} else {
|
||||
Error("$filename_path does not exist or is not readable.");
|
||||
|
|
Loading…
Reference in New Issue