Merge branch 'master' into storageareas

This commit is contained in:
Isaac Connor 2019-08-07 11:21:19 -04:00
commit d4b59211cd
18 changed files with 643 additions and 431 deletions

View File

@ -186,6 +186,7 @@ CREATE TABLE `Events` (
`Id` bigint unsigned NOT NULL auto_increment, `Id` bigint unsigned NOT NULL auto_increment,
`MonitorId` int(10) unsigned NOT NULL default '0', `MonitorId` int(10) unsigned NOT NULL default '0',
`StorageId` smallint(5) unsigned default 0, `StorageId` smallint(5) unsigned default 0,
`SecondaryStorageId` smallint(5) unsigned default 0,
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Cause` varchar(32) NOT NULL default '', `Cause` varchar(32) NOT NULL default '',
`StartTime` datetime default NULL, `StartTime` datetime default NULL,

51
db/zm_update-1.33.14.sql Normal file
View File

@ -0,0 +1,51 @@
--
-- Add CopyTo action to Filters
--
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Filters'
AND column_name = 'AutoCopy'
) > 0,
"SELECT 'Column AutoCopy already exists in Filters'",
"ALTER TABLE Filters ADD `AutoCopy` tinyint(3) unsigned NOT NULL default '0' AFTER `AutoMove`"
));
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 = 'AutoCopyTo'
) > 0,
"SELECT 'Column AutoCopyTo already exists in Filters'",
"ALTER TABLE Filters ADD `AutoCopyTo` smallint(5) unsigned NOT NULL default '0' AFTER `AutoCopy`"
));
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 = 'Query_json'
) > 0,
"SELECT 'Column Query_json already exists in Filters'",
"ALTER TABLE `Filters` Change `Query` `Query_json` text NOT NULL"
));
PREPARE stmt FROM @s;
EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Events'
AND column_name = 'SecondaryStorageId'
) > 0,
"SELECT 'Column SecondaryStorageId already exists in Events'",
"ALTER TABLE `Events` ADD `SecondaryStorageId` smallint(5) unsigned default 0 AFTER `StorageId`"
));
PREPARE stmt FROM @s;
EXECUTE stmt;

View File

@ -189,11 +189,17 @@ Add the following to the bottom of the file
:: ::
# Backports repository # Backports repository
deb http://httpredir.debian.org/debian jessie-backports main contrib non-free deb http://archive.debian.org/debian/ jessie-backports main contrib non-free
CTRL+o and <Enter> to save CTRL+o and <Enter> to save
CTRL+x to exit CTRL+x to exit
Run the following
::
echo 'Acquire::Check-Valid-Until no;' > /etc/apt/apt.conf.d/99no-check-valid-until
**Step 5:** Install ZoneMinder **Step 5:** Install ZoneMinder
:: ::

View File

@ -41,6 +41,7 @@ require Number::Bytes::Human;
require Date::Parse; require Date::Parse;
require POSIX; require POSIX;
use Date::Format qw(time2str); use Date::Format qw(time2str);
use Time::HiRes qw(gettimeofday tv_interval);
#our @ISA = qw(ZoneMinder::Object); #our @ISA = qw(ZoneMinder::Object);
use parent qw(ZoneMinder::Object); use parent qw(ZoneMinder::Object);
@ -63,6 +64,7 @@ $serial = $primary_key = 'Id';
Id Id
MonitorId MonitorId
StorageId StorageId
SecondaryStorageId
Name Name
Cause Cause
StartTime StartTime
@ -163,7 +165,8 @@ sub RelativePath {
if ( $event->Time() ) { if ( $event->Time() ) {
$$event{RelativePath} = join('/', $$event{RelativePath} = join('/',
$event->{MonitorId}, $event->{MonitorId},
POSIX::strftime( '%y/%m/%d/%H/%M/%S', POSIX::strftime(
'%y/%m/%d/%H/%M/%S',
localtime($event->Time()) localtime($event->Time())
), ),
); );
@ -203,7 +206,8 @@ sub LinkPath {
if ( $event->Time() ) { if ( $event->Time() ) {
$$event{LinkPath} = join('/', $$event{LinkPath} = join('/',
$event->{MonitorId}, $event->{MonitorId},
POSIX::strftime( '%y/%m/%d', POSIX::strftime(
'%y/%m/%d',
localtime($event->Time()) localtime($event->Time())
), ),
'.'.$$event{Id} '.'.$$event{Id}
@ -282,10 +286,10 @@ sub GenerateVideo {
$file_scale =~ s/_00//; $file_scale =~ s/_00//;
$file_scale =~ s/(_\d+)0+$/$1/; $file_scale =~ s/(_\d+)0+$/$1/;
$file_scale = 's'.$file_scale; $file_scale = 's'.$file_scale;
push( @file_parts, $file_scale ); push @file_parts, $file_scale;
} elsif ( $size ) { } elsif ( $size ) {
my $file_size = 'S'.$size; my $file_size = 'S'.$size;
push( @file_parts, $file_size ); push @file_parts, $file_size;
} }
my $video_file = join('-', $video_name, $file_parts[0], $file_parts[1] ).'.'.$format; my $video_file = join('-', $video_name, $file_parts[0], $file_parts[1] ).'.'.$format;
if ( $overwrite || !-s $video_file ) { if ( $overwrite || !-s $video_file ) {
@ -393,7 +397,11 @@ sub delete {
sub delete_files { sub delete_files {
my $event = shift; my $event = shift;
my $Storage = @_ ? $_[0] : new ZoneMinder::Storage($$event{StorageId}); foreach my $Storage (
@_ ? ($_[0]) : (
new ZoneMinder::Storage($$event{StorageId}),
( $$event{SecondaryStorageId} ? new ZoneMinder::Storage($$event{SecondaryStorageId}) : () ),
) ) {
my $storage_path = $Storage->Path(); my $storage_path = $Storage->Path();
if ( ! $storage_path ) { if ( ! $storage_path ) {
@ -438,7 +446,7 @@ sub delete_files {
my $command = "/bin/rm -rf $storage_path/$event_path"; my $command = "/bin/rm -rf $storage_path/$event_path";
ZoneMinder::General::executeShellCommand($command); ZoneMinder::General::executeShellCommand($command);
} }
} } # end if event_path
if ( $event->Scheme() eq 'Deep' ) { if ( $event->Scheme() eq 'Deep' ) {
my $link_path = $event->LinkPath(); my $link_path = $event->LinkPath();
@ -447,7 +455,8 @@ sub delete_files {
( $link_path ) = ( $link_path =~ /^(.*)$/ ); # De-taint ( $link_path ) = ( $link_path =~ /^(.*)$/ ); # De-taint
unlink($storage_path.'/'.$link_path) or Error("Unable to unlink '$storage_path/$link_path': $!"); unlink($storage_path.'/'.$link_path) or Error("Unable to unlink '$storage_path/$link_path': $!");
} }
} } # end if Scheme eq Deep
} # end foreach Storage
} # end sub delete_files } # end sub delete_files
sub StorageId { sub StorageId {
@ -519,7 +528,7 @@ sub DiskSpace {
return $_[0]{DiskSpace}; return $_[0]{DiskSpace};
} }
sub MoveTo { sub CopyTo {
my ( $self, $NewStorage ) = @_; my ( $self, $NewStorage ) = @_;
my $OldStorage = $self->Storage(undef); my $OldStorage = $self->Storage(undef);
@ -531,9 +540,9 @@ sub MoveTo {
# We do this before bothering to lock the event # We do this before bothering to lock the event
my ( $NewPath ) = ( $NewStorage->Path() =~ /^(.*)$/ ); # De-taint my ( $NewPath ) = ( $NewStorage->Path() =~ /^(.*)$/ ); # De-taint
if ( ! $$NewStorage{Id} ) { if ( ! $$NewStorage{Id} ) {
return "New storage does not have an id. Moving will not happen."; return 'New storage does not have an id. Moving will not happen.';
} elsif ( $$NewStorage{Id} == $$self{StorageId} ) { } elsif ( $$NewStorage{Id} == $$self{StorageId} ) {
return "Event is already located at " . $NewPath; return 'Event is already located at ' . $NewPath;
} elsif ( !$NewPath ) { } elsif ( !$NewPath ) {
return "New path ($NewPath) is empty."; return "New path ($NewPath) is empty.";
} elsif ( ! -e $NewPath ) { } elsif ( ! -e $NewPath ) {
@ -545,7 +554,7 @@ sub MoveTo {
# data is reloaded, so need to check that the move hasn't already happened. # data is reloaded, so need to check that the move hasn't already happened.
if ( $$self{StorageId} == $$NewStorage{Id} ) { if ( $$self{StorageId} == $$NewStorage{Id} ) {
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
return "Event has already been moved by someone else."; return 'Event has already been moved by someone else.';
} }
if ( $$OldStorage{Id} != $$self{StorageId} ) { if ( $$OldStorage{Id} != $$self{StorageId} ) {
@ -559,7 +568,7 @@ sub MoveTo {
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
return "New path and old path are the same! $NewPath"; return "New path and old path are the same! $NewPath";
} }
Debug("Moving event $$self{Id} from $OldPath to $NewPath"); Debug("Copying event $$self{Id} from $OldPath to $NewPath");
my $moved = 0; my $moved = 0;
@ -580,7 +589,7 @@ sub MoveTo {
} }
my $event_path = 'events/'.$self->RelativePath(); my $event_path = 'events/'.$self->RelativePath();
Info("Making dir ectory $event_path/"); Debug("Making directory $event_path/");
if ( ! $bucket->add_key( $event_path.'/','' ) ) { if ( ! $bucket->add_key( $event_path.'/','' ) ) {
die "Unable to add key for $event_path/"; die "Unable to add key for $event_path/";
} }
@ -590,7 +599,7 @@ Debug("Files to move @files");
for my $file (@files) { for my $file (@files) {
next if $file =~ /^\./; next if $file =~ /^\./;
( $file ) = ( $file =~ /^(.*)$/ ); # De-taint ( $file ) = ( $file =~ /^(.*)$/ ); # De-taint
my $starttime = time; my $starttime = [gettimeofday];
Debug("Moving file $file to $NewPath"); Debug("Moving file $file to $NewPath");
my $size = -s $file; my $size = -s $file;
if ( ! $size ) { if ( ! $size ) {
@ -605,7 +614,7 @@ Debug("Files to move @files");
if ( ! $bucket->add_key($filename, $file_contents) ) { if ( ! $bucket->add_key($filename, $file_contents) ) {
die "Unable to add key for $filename"; die "Unable to add key for $filename";
} }
my $duration = time - $starttime; my $duration = tv_interval($starttime);
Debug('PUT to S3 ' . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . Number::Bytes::Human::format_bytes($duration?$size/$duration:$size) . '/sec'); Debug('PUT to S3 ' . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . Number::Bytes::Human::format_bytes($duration?$size/$duration:$size) . '/sec');
} # end foreach file. } # end foreach file.
@ -636,21 +645,21 @@ Debug("Files to move @files");
my @files = glob("$OldPath/*"); my @files = glob("$OldPath/*");
if ( ! @files ) { if ( ! @files ) {
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
return "No files to move."; return 'No files to move.';
} }
for my $file (@files) { for my $file (@files) {
next if $file =~ /^\./; next if $file =~ /^\./;
( $file ) = ( $file =~ /^(.*)$/ ); # De-taint ( $file ) = ( $file =~ /^(.*)$/ ); # De-taint
my $starttime = time; my $starttime = [gettimeofday];
Debug("Moving file $file to $NewPath"); Debug("Moving file $file to $NewPath");
my $size = -s $file; my $size = -s $file;
if ( ! File::Copy::copy( $file, $NewPath ) ) { if ( ! File::Copy::copy( $file, $NewPath ) ) {
$error .= "Copy failed: for $file to $NewPath: $!"; $error .= "Copy failed: for $file to $NewPath: $!";
last; last;
} }
my $duration = time - $starttime; my $duration = tv_interval($starttime);
Debug("Copied " . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . ($duration?Number::Bytes::Human::format_bytes($size/$duration):'inf') . "/sec"); Debug('Copied ' . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . ($duration?Number::Bytes::Human::format_bytes($size/$duration):'inf') . '/sec');
} # end foreach file. } # end foreach file.
} # end if ! moved } # end if ! moved
@ -658,6 +667,15 @@ Debug("Files to move @files");
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
return $error; return $error;
} }
} # end sub CopyTo
sub MoveTo {
my ( $self, $NewStorage ) = @_;
my $OldStorage = $self->Storage(undef);
my $error = $self->CopyTo($NewStorage);
return $error if $error;
# Succeeded in copying all files, so we may now update the Event. # Succeeded in copying all files, so we may now update the Event.
$$self{StorageId} = $$NewStorage{Id}; $$self{StorageId} = $$NewStorage{Id};
@ -667,10 +685,8 @@ Debug("Files to move @files");
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
return $error; return $error;
} }
Debug("Committing");
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
$self->delete_files($OldStorage); $self->delete_files($OldStorage);
Debug("Done deleting files, returning");
return $error; return $error;
} # end sub MoveTo } # end sub MoveTo

View File

@ -132,11 +132,13 @@ sub Sql {
my $self = shift; my $self = shift;
$$self{Sql} = shift if @_; $$self{Sql} = shift if @_;
if ( ! $$self{Sql} ) { if ( ! $$self{Sql} ) {
if ( !$self->{Query} ) { $self->{Sql} = '';
Warning('No Query in filter.'); if ( ! $self->{Query_json} ) {
Warning("No query in Filter!");
return; return;
} }
my $filter_expr = ZoneMinder::General::jsonDecode($self->{Query});
my $filter_expr = ZoneMinder::General::jsonDecode($self->{Query_json});
my $sql = 'SELECT E.*, my $sql = 'SELECT E.*,
unix_timestamp(E.StartTime) as Time, unix_timestamp(E.StartTime) as Time,
M.Name as MonitorName, M.Name as MonitorName,
@ -146,7 +148,6 @@ sub Sql {
INNER JOIN Monitors as M on M.Id = E.MonitorId INNER JOIN Monitors as M on M.Id = E.MonitorId
LEFT JOIN Storage as S on S.Id = E.StorageId LEFT JOIN Storage as S on S.Id = E.StorageId
'; ';
$self->{Sql} = '';
if ( $filter_expr->{terms} ) { if ( $filter_expr->{terms} ) {
foreach my $term ( @{$filter_expr->{terms}} ) { foreach my $term ( @{$filter_expr->{terms}} ) {

View File

@ -46,56 +46,13 @@ use ZoneMinder::Database qw(:all);
use POSIX; use POSIX;
use vars qw/ $table $primary_key /; use vars qw/ $table $primary_key %fields/;
$table = 'Storage'; $table = 'Storage';
$primary_key = 'Id'; $primary_key = 'Id';
#__PACKAGE__->table('Storage'); #__PACKAGE__->table('Storage');
#__PACKAGE__->primary_key('Id'); #__PACKAGE__->primary_key('Id');
%fields = map { $_ => $_ } qw( Id Name Path DoDelete ServerId Type Url DiskSpace Scheme );
sub find {
shift if $_[0] eq 'ZoneMinder::Storage';
my %sql_filters = @_;
my $sql = 'SELECT * FROM Storage';
my @sql_filters;
my @sql_values;
if ( exists $sql_filters{Id} ) {
push @sql_filters , ' Id=? ';
push @sql_values, $sql_filters{Id};
}
if ( exists $sql_filters{Name} ) {
push @sql_filters , ' Name = ? ';
push @sql_values, $sql_filters{Name};
}
if ( exists $sql_filters{ServerId} ) {
push @sql_filters, ' ServerId = ?';
push @sql_values, $sql_filters{ServerId};
}
$sql .= ' WHERE ' . join(' AND ', @sql_filters) if @sql_filters;
$sql .= ' LIMIT ' . $sql_filters{limit} if $sql_filters{limit};
my $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql )
or Fatal( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() );
my $res = $sth->execute( @sql_values )
or Fatal( "Can't execute '$sql': ".$sth->errstr() );
my @results;
while( my $db_filter = $sth->fetchrow_hashref() ) {
my $filter = new ZoneMinder::Storage( $$db_filter{Id}, $db_filter );
push @results, $filter;
} # end while
Debug("SQL: $sql returned " . @results . ' results');
return @results;
}
sub find_one {
my @results = find(@_);
return $results[0] if @results;
}
sub Path { sub Path {
if ( @_ > 1 ) { if ( @_ > 1 ) {

View File

@ -240,6 +240,7 @@ sub getFilters {
or AutoDelete = 1 or AutoDelete = 1
or UpdateDiskSpace = 1 or UpdateDiskSpace = 1
or AutoMove = 1 or AutoMove = 1
or AutoCopy = 1
) ORDER BY Name'; ) ORDER BY Name';
my $sth = $dbh->prepare_cached($sql) my $sth = $dbh->prepare_cached($sql)
or Fatal("Unable to prepare '$sql': ".$dbh->errstr()); or Fatal("Unable to prepare '$sql': ".$dbh->errstr());
@ -283,6 +284,7 @@ sub checkFilter {
($filter->{AutoMessage}?'message':()), ($filter->{AutoMessage}?'message':()),
($filter->{AutoExecute}?'execute':()), ($filter->{AutoExecute}?'execute':()),
($filter->{AutoMove}?'move':()), ($filter->{AutoMove}?'move':()),
($filter->{AutoCopy}?'copy':()),
($filter->{UpdateDiskSpace}?'update disk space':()), ($filter->{UpdateDiskSpace}?'update disk space':()),
), ),
'returned' , scalar @Events , 'events', 'returned' , scalar @Events , 'events',
@ -343,6 +345,23 @@ sub checkFilter {
$_ = $Event->MoveTo($NewStorage); $_ = $Event->MoveTo($NewStorage);
Error($_) if $_; Error($_) if $_;
} }
if ( $filter->{AutoCopy} ) {
# Copy To is different from MoveTo in that it JUST copies the files
# So we still need to update the Event object with the new SecondaryStorageId
my $NewStorage = ZoneMinder::Storage->find_one(Id=>$filter->{AutoCopyTo});
if ( $NewStorage ) {
$_ = $Event->CopyTo($NewStorage);
if ( $_ ) {
$ZoneMinder::Database::dbh->commit();
Error($_);
} else {
$Event->save({SecondaryStorageId=>$$NewStorage{Id}});
$ZoneMinder::Database::dbh->commit();
}
} else {
Error("No storage area found for copy to operation. AutoCopyTo was $$filter{AutoCopyTo}");
}
} # end if AutoCopy
if ( $filter->{UpdateDiskSpace} ) { if ( $filter->{UpdateDiskSpace} ) {
$ZoneMinder::Database::dbh->begin_work(); $ZoneMinder::Database::dbh->begin_work();
@ -361,7 +380,7 @@ sub checkFilter {
$ZoneMinder::Database::dbh->commit(); $ZoneMinder::Database::dbh->commit();
} # end if UpdateDiskSpace } # end if UpdateDiskSpace
} # end foreach event } # end foreach event
} } # end sub checkFilter
sub generateVideo { sub generateVideo {
my $filter = shift; my $filter = shift;
@ -623,7 +642,7 @@ sub substituteTags {
my $Monitor = $Event->Monitor() if $need_monitor; my $Monitor = $Event->Monitor() if $need_monitor;
# Do we need the image information too? # Do we need the image information too?
my $need_images = $text =~ /%(?:EPI1|EPIM|EI1|EIM|EI1A|EIMA)%/; my $need_images = $text =~ /%(?:EPI1|EPIM|EI1|EIM|EI1A|EIMA|EIMOD)%/;
my $first_alarm_frame; my $first_alarm_frame;
my $max_alarm_frame; my $max_alarm_frame;
my $max_alarm_score = 0; my $max_alarm_score = 0;

View File

@ -1 +1 @@
1.33.13 1.33.14

View File

@ -12,6 +12,7 @@ class Event {
'Name', 'Name',
'MonitorId', 'MonitorId',
'StorageId', 'StorageId',
'SecondaryStorageId',
'Name', 'Name',
'Cause', 'Cause',
'StartTime', 'StartTime',
@ -85,6 +86,19 @@ class Event {
return $this->{'Storage'}; return $this->{'Storage'};
} }
public function SecondaryStorage( $new = null ) {
if ( $new ) {
$this->{'SecondaryStorage'} = $new;
}
if ( ! ( array_key_exists('SecondaryStorage', $this) and $this->{'SecondaryStorage'} ) ) {
if ( isset($this->{'SecondaryStorageId'}) and $this->{'SecondaryStorageId'} )
$this->{'SecondaryStorage'} = Storage::find_one(array('Id'=>$this->{'SecondaryStorageId'}));
if ( ! ( array_key_exists('SecondaryStorage', $this) and $this->{'SecondaryStorage'} ) )
$this->{'SecondaryStorage'} = new Storage(NULL);
}
return $this->{'SecondaryStorage'};
}
public function Monitor() { public function Monitor() {
if ( isset($this->{'MonitorId'}) ) { if ( isset($this->{'MonitorId'}) ) {
$Monitor = Monitor::find_one(array('Id'=>$this->{'MonitorId'})); $Monitor = Monitor::find_one(array('Id'=>$this->{'MonitorId'}));

View File

@ -1,9 +1,11 @@
<?php <?php
namespace ZM; namespace ZM;
require_once('Object.php');
class Filter { class Filter extends ZM_Object {
protected static $table = 'Filters';
public $defaults = array( protected $defaults = array(
'Id' => null, 'Id' => null,
'Name' => '', 'Name' => '',
'AutoExecute' => 0, 'AutoExecute' => 0,
@ -16,68 +18,55 @@ public $defaults = array(
'AutoMessage' => 0, 'AutoMessage' => 0,
'AutoMove' => 0, 'AutoMove' => 0,
'AutoMoveTo' => 0, 'AutoMoveTo' => 0,
'AutoCopy' => 0,
'AutoCopyTo' => 0,
'UpdateDiskSpace' => 0, 'UpdateDiskSpace' => 0,
'Background' => 0, 'Background' => 0,
'Concurrent' => 0, 'Concurrent' => 0,
'limit' => 100, 'Query_json' => '',
'Query' => array(),
'sort_field' => ZM_WEB_EVENT_SORT_FIELD,
'sort_asc' => ZM_WEB_EVENT_SORT_ORDER,
); );
public function __construct( $IdOrRow=NULL ) { public function Query_json() {
$row = NULL; if ( func_num_args( ) ) {
if ( $IdOrRow ) { $this->{'Query_json'} = func_get_arg(0);;
if ( is_integer($IdOrRow) or is_numeric($IdOrRow) ) { $this->{'Query'} = jsonDecode($this->{'Query_json'});
$row = dbFetchOne('SELECT * FROM Filters WHERE Id=?', NULL, array($IdOrRow));
if ( ! $row ) {
Error('Unable to load Filter record for Id=' . $IdOrRow);
} }
} elseif ( is_array($IdOrRow) ) { return $this->{'Query_json'};
$row = $IdOrRow;
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Error("Unknown argument passed to Filter Constructor from $file:$line)");
Error("Unknown argument passed to Filter Constructor ($IdOrRow)");
return;
} }
} # end if isset($IdOrRow)
if ( $row ) { public function Query() {
foreach ($row as $k => $v) { if ( func_num_args( ) ) {
$this->{$k} = $v; $this->{'Query'} = func_get_arg(0);;
$this->{'Query_json'} = jsonEncode($this->{'Query'});
} }
if ( array_key_exists('Query', $this) and $this->{'Query'} ) { if ( !array_key_exists('Query', $this) ) {
$this->{'Query'} = jsonDecode($this->{'Query'}); if ( array_key_exists('Query_json', $this) and $this->{'Query_json'} ) {
$this->{'Query'} = jsonDecode($this->{'Query_json'});
} else { } else {
$this->{'Query'} = array(); $this->{'Query'} = array();
} }
}
} // end function __construct
public function __call( $fn, array $args ) {
if ( count( $args ) ) {
$this->{$fn} = $args[0];
}
if ( array_key_exists( $fn, $this ) ) {
return $this->{$fn};
} else if ( array_key_exists( $fn, $this->defaults ) ) {
$this->{$fn} = $this->defaults{$fn};
return $this->{$fn};
} else { } else {
if ( !is_array($this->{'Query'}) ) {
$backTrace = debug_backtrace(); # Handle existence of both Query_json and Query in the row
$file = $backTrace[1]['file']; $this->{'Query'} = jsonDecode($this->{'Query_json'});
$line = $backTrace[1]['line'];
Warning( "Unknown function call Filter->$fn from $file:$line" );
} }
} }
return $this->{'Query'};
}
public static function find( $parameters = array(), $options = array() ) {
return ZM_Object::_find(get_class(), $parameters, $options);
}
public static function find_one( $parameters = array(), $options = array() ) {
return ZM_Object::_find_one(get_class(), $parameters, $options);
}
public function terms( ) { public function terms( ) {
if ( func_num_args() ) { if ( func_num_args() ) {
$this->Query()['terms'] = func_get_arg(0); $Query = $this->Query();
$Query['terms'] = func_get_arg(0);
$this->Query($Query);
} }
if ( isset( $this->Query()['terms'] ) ) { if ( isset( $this->Query()['terms'] ) ) {
return $this->Query()['terms']; return $this->Query()['terms'];
@ -88,106 +77,42 @@ public $defaults = array(
// The following three fields are actually stored in the Query // The following three fields are actually stored in the Query
public function sort_field( ) { public function sort_field( ) {
if ( func_num_args( ) ) { if ( func_num_args( ) ) {
$this->Query()['sort_field'] = func_get_arg(0); $Query = $this->Query();
$Query['sort_field'] = func_get_arg(0);
$this->Query($Query);
} }
if ( isset( $this->Query()['sort_field'] ) ) { if ( isset( $this->Query()['sort_field'] ) ) {
return $this->{'Query'}['sort_field']; return $this->{'Query'}['sort_field'];
} }
return $this->defaults{'sort_field'}; return ZM_WEB_EVENT_SORT_FIELD;
#return $this->defaults{'sort_field'};
} }
public function sort_asc( ) { public function sort_asc( ) {
if ( func_num_args( ) ) { if ( func_num_args( ) ) {
$this->{'Query'}['sort_asc'] = func_get_arg(0); $Query = $this->Query();
$Query['sort_asc'] = func_get_arg(0);
$this->Query($Query);
} }
if ( isset( $this->Query()['sort_asc'] ) ) { if ( isset( $this->Query()['sort_asc'] ) ) {
return $this->{'Query'}['sort_asc']; return $this->{'Query'}['sort_asc'];
} }
return $this->defaults{'sort_asc'}; return ZM_WEB_EVENT_SORT_ORDER;
#return $this->defaults{'sort_asc'};
} }
public function limit( ) { public function limit( ) {
if ( func_num_args( ) ) { if ( func_num_args( ) ) {
$this->{'Query'}['limit'] = func_get_arg(0); $Query = $this->Query();
$Query['limit'] = func_get_arg(0);
$this->Query($Query);
} }
if ( isset( $this->Query()['limit'] ) ) if ( isset( $this->Query()['limit'] ) )
return $this->{'Query'}['limit']; return $this->{'Query'}['limit'];
return $this->defaults{'limit'}; return 100;
#return $this->defaults{'limit'};
} }
public static function find( $parameters = null, $options = null ) {
$filters = array();
$sql = 'SELECT * FROM Filters ';
$values = array();
if ( $parameters ) {
$fields = array();
$sql .= 'WHERE ';
foreach ( $parameters as $field => $value ) {
if ( $value == null ) {
$fields[] = $field.' IS NULL';
} else if ( is_array( $value ) ) {
$func = function(){return '?';};
$fields[] = $field.' IN ('.implode(',', array_map($func, $value)). ')';
$values += $value;
} else {
$fields[] = $field.'=?';
$values[] = $value;
}
}
$sql .= implode(' AND ', $fields);
}
if ( $options ) {
if ( isset($options['order']) ) {
$sql .= ' ORDER BY ' . $options['order'];
}
if ( isset($options['limit']) ) {
if ( is_integer($options['limit']) or ctype_digit($options['limit']) ) {
$sql .= ' LIMIT ' . $options['limit'];
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Error("Invalid value for limit(".$options['limit'].") passed to Filter::find from $file:$line");
return array();
}
}
}
$result = dbQuery($sql, $values);
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Filter');
foreach ( $results as $row => $obj ) {
$filters[] = $obj;
}
return $filters;
} # end find()
public static function find_one( $parameters = array() ) {
$results = Filter::find($parameters, array('limit'=>1));
if ( ! sizeof($results) ) {
return;
}
return $results[0];
} # end find_one()
public function delete() {
dbQuery('DELETE FROM Filters WHERE Id=?', array($this->{'Id'}));
} # end function delete()
public function set( $data ) {
foreach ($data as $k => $v) {
if ( is_array( $v ) ) {
$this->{$k} = $v;
} else if ( is_string( $v ) ) {
$this->{$k} = trim( $v );
} else if ( is_integer( $v ) ) {
$this->{$k} = $v;
} else if ( is_bool( $v ) ) {
$this->{$k} = $v;
} else {
Error( "Unknown type $k => $v of var " . gettype( $v ) );
$this->{$k} = $v;
}
}
} # end function set
public function control($command, $server_id=null) { public function control($command, $server_id=null) {
$Servers = $server_id ? Server::find(array('Id'=>$server_id)) : Server::find(); $Servers = $server_id ? Server::find(array('Id'=>$server_id)) : Server::find();
if ( !count($Servers) and !$server_id ) { if ( !count($Servers) and !$server_id ) {

254
web/includes/Object.php Normal file
View File

@ -0,0 +1,254 @@
<?php
namespace ZM;
require_once('database.php');
$object_cache = array();
class ZM_Object {
public function __construct($IdOrRow = NULL) {
$class = get_class($this);
global $object_cache;
if ( ! isset($object_cache[$class]) )
$object_cache[$class] = array();
$cache = $object_cache[$class];
$table = $class::$table;
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer($IdOrRow) or ctype_digit($IdOrRow) ) {
$row = dbFetchOne("SELECT * FROM `$table` WHERE `Id`=?", NULL, array($IdOrRow));
if ( !$row ) {
Error("Unable to load $class record for Id=$IdOrRow");
}
} elseif ( is_array($IdOrRow) ) {
$row = $IdOrRow;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
$cache[$row['Id']] = $this;
} else {
# Set defaults
foreach ( $this->defaults as $k => $v ) $this->{$k} = $v;
}
}
public function __call($fn, array $args){
if ( count($args) ) {
$this->{$fn} = $args[0];
}
if ( array_key_exists($fn, $this) ) {
return $this->{$fn};
} else {
if ( array_key_exists($fn, $this->defaults) ) {
return $this->defaults{$fn};
} else {
$backTrace = debug_backtrace();
Warning("Unknown function call Sensor->$fn from ".print_r($backTrace,true));
}
}
}
public static function _find($class, $parameters = null, $options = null ) {
$table = $class::$table;
$filters = array();
$sql = "SELECT * FROM `$table` ";
$values = array();
if ( $parameters ) {
$fields = array();
$sql .= 'WHERE ';
foreach ( $parameters as $field => $value ) {
if ( $value == null ) {
$fields[] = '`'.$field.'` IS NULL';
} else if ( is_array($value) ) {
$func = function(){return '?';};
$fields[] = '`'.$field.'` IN ('.implode(',', array_map($func, $value)). ')';
$values += $value;
} else {
$fields[] = '`'.$field.'`=?';
$values[] = $value;
}
}
$sql .= implode(' AND ', $fields );
}
if ( $options ) {
if ( isset($options['order']) ) {
$sql .= ' ORDER BY ' . $options['order'];
}
if ( isset($options['limit']) ) {
if ( is_integer($options['limit']) or ctype_digit($options['limit']) ) {
$sql .= ' LIMIT ' . $options['limit'];
} else {
Error('Invalid value for limit('.$options['limit'].') passed to '.get_class()."::find from ".print_r($backTrace,true));
return array();
}
}
}
$rows = dbFetchAll($sql, NULL, $values);
$results = array();
if ( $rows ) {
foreach ( $rows as $row ) {
array_push($results , new $class($row));
}
}
return $results;
} # end public function find()
public static function _find_one($class, $parameters = array(), $options = array() ) {
global $object_cache;
if ( ! isset($object_cache[$class]) )
$object_cache[$class] = array();
$cache = $object_cache[$class];
if (
( count($parameters) == 1 ) and
isset($parameters['Id']) and
isset($cache[$parameters['Id']]) ) {
return $cache[$parameters['Id']];
}
$options['limit'] = 1;
$results = ZM_Object::_find($class, $parameters, $options);
if ( ! sizeof($results) ) {
return;
}
return $results[0];
}
public static function Objects_Indexed_By_Id($class) {
$results = array();
foreach ( ZM_Object::_find($class, null, array('order'=>'lower(Name)')) as $Object ) {
$results[$Object->Id()] = $Object;
}
return $results;
}
public function to_json() {
$json = array();
foreach ($this->defaults as $key => $value) {
if ( is_callable(array($this, $key)) ) {
$json[$key] = $this->$key();
} else if ( array_key_exists($key, $this) ) {
$json[$key] = $this->{$key};
} else {
$json[$key] = $this->defaults{$key};
}
}
return json_encode($json);
}
public function set($data) {
foreach ( $data as $k => $v ) {
if ( method_exists($this, $k) ) {
$this->{$k}($v);
} else {
if ( is_array($v) ) {
# perhaps should turn into a comma-separated string
$this->{$k} = implode(',', $v);
} else if ( is_string($v) ) {
if ( $v == '' and array_key_exists($k, $this->defaults) ) {
$this->{$k} = $this->defaults[$k];
} else {
$this->{$k} = trim($v);
}
} else if ( is_integer($v) ) {
$this->{$k} = $v;
} else if ( is_bool($v) ) {
$this->{$k} = $v;
} else if ( is_null($v) ) {
$this->{$k} = $v;
} else {
Error( "Unknown type $k => $v of var " . gettype( $v ) );
$this->{$k} = $v;
}
} # end if method_exists
} # end foreach $data as $k=>$v
}
public function changes( $new_values ) {
$changes = array();
foreach ( $new_values as $field => $value ) {
if ( method_exists($this, $field) ) {
$old_value = $this->$field();
Logger::Debug("Checking method $field () ".print_r($old_value,true)." => " . print_r($value,true));
if ( is_array($old_value) ) {
$diff = array_recursive_diff($old_value, $value);
Logger::Debug("Checking method $field () diff is".print_r($diff,true));
if ( count($diff) ) {
$changes[$field] = $value;
}
} else if ( $this->$field() != $value ) {
$changes[$field] = $value;
}
} else if ( array_key_exists($field, $this) ) {
Logger::Debug("Checking field $field => ".$this->{$field} . " ?= " .$value);
if ( $this->{$field} != $value ) {
$changes[$field] = $value;
}
} else if ( array_key_exists($field, $this->defaults) ) {
Logger::Debug("Checking default $field => ".$this->defaults[$field] . " " .$value);
if ( $this->defaults[$field] != $value ) {
$changes[$field] = $value;
}
}
#if ( (!array_key_exists($field, $this)) or ( $this->{$field} != $new_values[$field] ) ) {
#Logger::Debug("Checking default $field => $default_value changes becaause" . $new_values[$field].' != '.$new_values[$field]);
#$changes[$field] = $new_values[$field];
##} else if {
#Logger::Debug("Checking default $field => $default_value changes becaause " . $new_values[$field].' != '.$new_values[$field]);
##array_push( $changes, [$field=>$defaults[$field]] );
#}
#} else {
#Logger::Debug("Checking default $field => $default_value not in new_values");
#}
} # end foreach default
return $changes;
} # end public function changes
public function save($new_values = null) {
$class = get_class($this);
$table = $class::$table;
if ( $new_values ) {
Logger::Debug("New values" . print_r($new_values,true));
$this->set($new_values);
}
if ( $this->Id() ) {
$fields = array_keys($this->defaults);
$sql = 'UPDATE '.$table.' SET '.implode(', ', array_map(function($field) {return '`'.$field.'`=?';}, $fields )) . ' WHERE Id=?';
$values = array_map(function($field){return $this->{$field};}, $fields);
$values[] = $this->{'Id'};
if ( dbQuery($sql, $values) )
return true;
} else {
$fields = $this->defaults;
unset($fields['Id']);
$sql = 'INSERT INTO '.$table.' ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, array_keys($fields))).') VALUES ('.implode(', ', array_map(function($field){return '?';}, array_values($fields))).')';
$values = array_map(function($field){return $this->{$field};}, array_keys($fields));
if ( dbQuery($sql, $values) ) {
$this->{'Id'} = dbInsertId();
return true;
}
}
return false;
} // end function save
public function delete() {
$class = get_class($this);
$table = $class::$table;
dbQuery("DELETE FROM $table WHERE Id=?", array($this->{'Id'}));
if ( isset($object_cache[$class]) and isset($object_cache[$class][$this->{'Id'}]) )
unset($object_cache[$class][$this->{'Id'}]);
}
} # end class Sensor Action
?>

View File

@ -2,10 +2,11 @@
namespace ZM; namespace ZM;
require_once('database.php'); require_once('database.php');
require_once('Event.php'); require_once('Event.php');
require_once('Object.php');
$storage_cache = array(); class Storage extends ZM_Object {
class Storage { protected static $table = 'Storage';
private $defaults = array( protected $defaults = array(
'Id' => null, 'Id' => null,
'Path' => '', 'Path' => '',
'Name' => '', 'Name' => '',
@ -16,31 +17,12 @@ class Storage {
'ServerId' => 0, 'ServerId' => 0,
'DoDelete' => 1, 'DoDelete' => 1,
); );
public static function find($parameters = array(), $options = array() ) {
return ZM_Object::_find(get_class(), $parameters, $options);
}
public function __construct( $IdOrRow = NULL ) { public static function find_one( $parameters = array(), $options = array() ) {
global $storage_cache; return ZM_Object::_find_one(get_class(), $parameters, $options);
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer($IdOrRow) or is_numeric($IdOrRow) ) {
$row = dbFetchOne('SELECT * FROM Storage WHERE Id=?', NULL, array($IdOrRow));
if ( ! $row ) {
Error('Unable to load Storage record for Id=' . $IdOrRow);
}
} else if ( is_array($IdOrRow) ) {
$row = $IdOrRow;
}
}
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
$storage_cache[$row['Id']] = $this;
} else {
$this->{'Name'} = '';
$this->{'Path'} = '';
$this->{'Type'} = 'local';
}
} }
public function Path() { public function Path() {
@ -66,93 +48,6 @@ class Storage {
return $this->{'Name'}; return $this->{'Name'};
} }
public function __call( $fn, array $args= NULL ) {
if ( count($args) ) {
$this->{$fn} = $args[0];
}
if ( array_key_exists($fn, $this) )
return $this->{$fn};
if ( array_key_exists($fn, $this->defaults) )
return $this->defaults{$fn};
$backTrace = debug_backtrace();
$file = $backTrace[0]['file'];
$line = $backTrace[0]['line'];
Warning("Unknown function call Storage->$fn from $file:$line");
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Warning("Unknown function call Storage->$fn from $file:$line");
}
public static function find_one( $parameters = null, $options = null ) {
global $storage_cache;
if (
( count($parameters) == 1 ) and
isset($parameters['Id']) and
isset($storage_cache[$parameters['Id']]) ) {
return $storage_cache[$parameters['Id']];
}
$results = Storage::find($parameters, $options);
if ( count($results) > 1 ) {
Error('Storage Returned more than 1');
return $results[0];
} else if ( count($results) ) {
return $results[0];
} else {
return null;
}
}
public static function find( $parameters = null, $options = null ) {
$sql = 'SELECT * FROM Storage ';
$values = array();
if ( $parameters ) {
$fields = array();
$sql .= 'WHERE ';
foreach ( $parameters as $field => $value ) {
if ( $value == null ) {
$fields[] = $field.' IS NULL';
} else if ( is_array($value) ) {
$func = function(){return '?';};
$fields[] = $field.' IN ('.implode(',', array_map($func, $value)).')';
$values += $value;
} else {
$fields[] = $field.'=?';
$values[] = $value;
}
}
$sql .= implode(' AND ', $fields);
} # end if parameters
if ( $options ) {
if ( isset($options['order']) ) {
$sql .= ' ORDER BY ' . $options['order'];
} # end if options
if ( isset($options['limit']) ) {
if ( is_integer($options['limit']) or ctype_digit($options['limit']) ) {
$sql .= ' LIMIT ' . $option['limit'];
} else {
$backTrace = debug_backtrace();
$file = $backTrace[1]['file'];
$line = $backTrace[1]['line'];
Error("Invalid value for limit(".$options['limit'].") passed to Control::find from $file:$line");
return array();
}
} # end if limit
} # end if options
$storage_areas = array();
$result = dbQuery($sql, $values);
if ( $result ) {
$results = $result->fetchALL();
foreach ( $results as $row ) {
$storage_areas[] = new Storage($row);
}
}
return $storage_areas;
} # end find()
public function disk_usage_percent() { public function disk_usage_percent() {
$path = $this->Path(); $path = $this->Path();
if ( ! $path ) { if ( ! $path ) {
@ -226,18 +121,5 @@ class Storage {
return $this->{'Server'}; return $this->{'Server'};
} }
public function to_json() {
$json = array();
foreach ($this->defaults as $key => $value) {
if ( is_callable(array($this, $key)) ) {
$json[$key] = $this->$key();
} else if ( array_key_exists($key, $this) ) {
$json[$key] = $this->{$key};
} else {
$json[$key] = $this->defaults{$key};
}
}
return json_encode($json);
}
} // end class Storage } // end class Storage
?> ?>

View File

@ -51,11 +51,30 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
$_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']); $_REQUEST['filter']['Query']['sort_asc'] = validStr($_REQUEST['filter']['Query']['sort_asc']);
$_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']); $_REQUEST['filter']['Query']['limit'] = validInt($_REQUEST['filter']['Query']['limit']);
if ( $action == 'execute' ) { if ( $action == 'execute' ) {
$tempFilterName = '_TempFilter'.time(); $_REQUEST['filter']['Name'] = '_TempFilter'.time();
$sql .= ' Name = \''.$tempFilterName.'\''; unset($_REQUEST['Id']);
} else { #$tempFilterName = '_TempFilter'.time();
$sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']); #$sql .= ' Name = \''.$tempFilterName.'\'';
#} else {
#$sql .= ' Name = '.dbEscape($_REQUEST['filter']['Name']);
} }
$_REQUEST['filter']['AutoCopy'] = empty($_REQUEST['filter']['AutoCopy']) ? 0 : 1;
$_REQUEST['filter']['AutoMove'] = empty($_REQUEST['filter']['AutoMove']) ? 0 : 1;
$_REQUEST['filter']['AutoArchive'] = empty($_REQUEST['filter']['AutoArchive']) ? 0 : 1;
$_REQUEST['filter']['AutoVideo'] = empty($_REQUEST['filter']['AutoVideo']) ? 0 : 1;
$_REQUEST['filter']['AutoUpload'] = empty($_REQUEST['filter']['AutoUpload']) ? 0 : 1;
$_REQUEST['filter']['AutoEmail'] = empty($_REQUEST['filter']['AutoEmail']) ? 0 : 1;
$_REQUEST['filter']['AutoMessage'] = empty($_REQUEST['filter']['AutoMessage']) ? 0 : 1;
$_REQUEST['filter']['AutoExecute'] = empty($_REQUEST['filter']['AutoExecute']) ? 0 : 1;
$_REQUEST['filter']['AutoDelete'] = empty($_REQUEST['filter']['AutoDelete']) ? 0 : 1;
$_REQUEST['filter']['UpdateDiskSpace'] = empty($_REQUEST['filter']['UpdateDiskSpace']) ? 0 : 1;
$_REQUEST['filter']['Background'] = empty($_REQUEST['filter']['Background']) ? 0 : 1;
$_REQUEST['filter']['Concurrent'] = empty($_REQUEST['filter']['Concurrent']) ? 0 : 1;
$changes = $filter->changes($_REQUEST['filter']);
ZM\Logger::Debug("Changes: " . print_r($changes,true));
if ( 0 ) {
$sql .= ', Query = '.dbEscape(jsonEncode($_REQUEST['filter']['Query'])); $sql .= ', Query = '.dbEscape(jsonEncode($_REQUEST['filter']['Query']));
$sql .= ', AutoArchive = '.(!empty($_REQUEST['filter']['AutoArchive']) ? 1 : 0); $sql .= ', AutoArchive = '.(!empty($_REQUEST['filter']['AutoArchive']) ? 1 : 0);
$sql .= ', AutoVideo = '. ( !empty($_REQUEST['filter']['AutoVideo']) ? 1 : 0); $sql .= ', AutoVideo = '. ( !empty($_REQUEST['filter']['AutoVideo']) ? 1 : 0);
@ -73,17 +92,25 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
$sql .= ', UpdateDiskSpace = '. ( !empty($_REQUEST['filter']['UpdateDiskSpace']) ? 1 : 0); $sql .= ', UpdateDiskSpace = '. ( !empty($_REQUEST['filter']['UpdateDiskSpace']) ? 1 : 0);
$sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0); $sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0);
$sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 1 : 0); $sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 1 : 0);
}
if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) { if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) {
if ( 0 ) {
dbQuery('UPDATE Filters SET '.$sql.' WHERE Id=?', array($_REQUEST['Id'])); dbQuery('UPDATE Filters SET '.$sql.' WHERE Id=?', array($_REQUEST['Id']));
}
$filter->save($changes);
if ( $filter->Background() ) if ( $filter->Background() )
$filter->control('stop'); $filter->control('stop');
} else { } else {
# COuld be execute
if ( 0 ) {
dbQuery('INSERT INTO Filters SET'.$sql); dbQuery('INSERT INTO Filters SET'.$sql);
$_REQUEST['Id'] = dbInsertId(); $_REQUEST['Id'] = dbInsertId();
$filter = new ZM\Filter($_REQUEST['Id']); $filter = new ZM\Filter($_REQUEST['Id']);
} }
if ( !empty($_REQUEST['filter']['Background']) ) $filter->save($changes);
}
if ( $filter->Background() )
$filter->control('start'); $filter->control('start');
if ( $action == 'execute' ) { if ( $action == 'execute' ) {

View File

@ -2518,4 +2518,45 @@ function format_duration($time, $separator=':') {
return sprintf('%02d%s%02d%s%02d', floor($time/3600), $separator, ($time/60)%60, $separator, $time%60); return sprintf('%02d%s%02d%s%02d', floor($time/3600), $separator, ($time/60)%60, $separator, $time%60);
} }
function array_recursive_diff($aArray1, $aArray2) {
$aReturn = array();
foreach ($aArray1 as $mKey => $mValue) {
if ( array_key_exists($mKey, $aArray2) ) {
if ( is_array($mValue) ) {
$aRecursiveDiff = array_recursive_diff($mValue, $aArray2[$mKey]);
if ( count($aRecursiveDiff) ) {
$aReturn[$mKey] = $aRecursiveDiff;
}
} else {
if ( $mValue != $aArray2[$mKey] ) {
$aReturn[$mKey] = $mValue;
}
}
} else {
$aReturn[$mKey] = $mValue;
}
}
# Now check for keys in array2 that are not in array1
foreach ($aArray2 as $mKey => $mValue) {
if ( array_key_exists($mKey, $aArray1) ) {
# Already checked it... I think.
#if ( is_array($mValue) ) {
#$aRecursiveDiff = array_recursive_diff($mValue, $aArray2[$mKey]);
#if ( count($aRecursiveDiff) ) {
#$aReturn[$mKey] = $aRecursiveDiff;
#}
#} else {
#if ( $mValue != $aArray2[$mKey] ) {
#$aReturn[$mKey] = $mValue;
#}
#}
} else {
$aReturn[$mKey] = $mValue;
}
}
return $aReturn;
}
?> ?>

View File

@ -132,6 +132,7 @@ $SLANG = array(
'AttrMaxScore' => 'Max. Score', 'AttrMaxScore' => 'Max. Score',
'AttrMonitorId' => 'Monitor Id', 'AttrMonitorId' => 'Monitor Id',
'AttrMonitorName' => 'Monitor Name', 'AttrMonitorName' => 'Monitor Name',
'AttrSecondaryStorageArea' => 'Secondary Storage Area',
'AttrStorageArea' => 'Storage Area', 'AttrStorageArea' => 'Storage Area',
'AttrFilterServer' => 'Server Filter is Running On', 'AttrFilterServer' => 'Server Filter is Running On',
'AttrMonitorServer' => 'Server Monitor is Running On', 'AttrMonitorServer' => 'Server Monitor is Running On',
@ -356,6 +357,7 @@ $SLANG = array(
'FilterArchiveEvents' => 'Archive all matches', 'FilterArchiveEvents' => 'Archive all matches',
'FilterUpdateDiskSpace' => 'Update used disk space', 'FilterUpdateDiskSpace' => 'Update used disk space',
'FilterDeleteEvents' => 'Delete all matches', 'FilterDeleteEvents' => 'Delete all matches',
'FilterCopyEvents' => 'Copy all matches',
'FilterMoveEvents' => 'Move all matches', 'FilterMoveEvents' => 'Move all matches',
'FilterEmailEvents' => 'Email details of all matches', 'FilterEmailEvents' => 'Email details of all matches',
'FilterExecuteEvents' => 'Execute command on all matches', 'FilterExecuteEvents' => 'Execute command on all matches',

View File

@ -134,7 +134,11 @@ if ( ! $Event->Id() ) {
<span id="dataDuration" title="<?php echo translate('Duration') ?>"><?php echo $Event->Length().'s' ?></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="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> <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>
<span id="Storage"> <?php echo human_filesize($Event->DiskSpace(null)) . ' on ' . $Event->Storage()->Name() ?></span> <span id="Storage">
<?php echo
human_filesize($Event->DiskSpace(null)) . ' on ' . $Event->Storage()->Name().
( $Event->SecondaryStorageId() ? ', ' . $Event->SecondaryStorage()->Name() :'' )
?></span>
<div id="closeWindow"><a href="#" onclick="<?php echo $popup ? 'window.close()' : 'window.history.back();return false;' ?>"><?php echo $popup ? translate('Close') : translate('Back') ?></a></div> <div id="closeWindow"><a href="#" onclick="<?php echo $popup ? 'window.close()' : 'window.history.back();return false;' ?>"><?php echo $popup ? translate('Close') : translate('Back') ?></a></div>
</div> </div>
<div id="menuBar1"> <div id="menuBar1">

View File

@ -22,36 +22,35 @@ if ( !canView('Events') ) {
$view = 'error'; $view = 'error';
return; return;
} }
require_once 'includes/Filter.php'; require_once('includes/Object.php');
require_once('includes/Storage.php');
require_once('includes/Filter.php');
parseSort(); parseSort();
$filterNames = array(''=>translate('ChooseFilter')); $filterNames = array(''=>translate('ChooseFilter'));
$filter = NULL; $filter = NULL;
foreach ( dbFetchAll('SELECT * FROM Filters ORDER BY Name') as $row ) { foreach ( ZM\Filter::find(null,array('order'=>'lower(Name)')) as $Filter ) {
$filterNames[$row['Id']] = $row['Id'] . ' ' . $row['Name']; $filterNames[$Filter->Id()] = $Filter->Id() . ' ' . $Filter->Name();
if ( $row['Background'] ) if ( $Filter->Background() )
$filterNames[$row['Id']] .= '*'; $filterNames[$Filter->Id()] .= '*';
if ( $row['Concurrent'] ) if ( $Filter->Concurrent() )
$filterNames[$row['Id']] .= '&'; $filterNames[$Filter->Id()] .= '&';
if ( isset($_REQUEST['Id']) && $_REQUEST['Id'] == $row['Id'] ) { if ( isset($_REQUEST['Id']) && ($_REQUEST['Id'] == $Filter->Id()) ) {
$filter = new ZM\Filter($row); $filter = $Filter;
} }
} }
if ( !$filter ) { if ( !$filter ) {
$filter = new ZM\Filter(); $filter = new ZM\Filter();
} }
if ( isset($_REQUEST['sort_field']) && isset($_REQUEST['filter']) ) { ZM\Logger::Debug("Query: " . $filter->Query_json());
$_REQUEST['filter']['Query']['sort_field'] = $_REQUEST['sort_field']; ZM\Logger::Debug("Query: " . print_r($filter->Query(), true));
$_REQUEST['filter']['Query']['sort_asc'] = $_REQUEST['sort_asc'];
$_REQUEST['filter']['Query']['limit'] = $_REQUEST['limit'];
}
if ( isset($_REQUEST['filter']) ) { if ( isset($_REQUEST['filter']) ) {
$filter->set($_REQUEST['filter']);
# Update our filter object with whatever changes we have made before saving # Update our filter object with whatever changes we have made before saving
#$filter->set($_REQUEST['filter']);
} }
$conjunctionTypes = getFilterQueryConjunctionTypes(); $conjunctionTypes = getFilterQueryConjunctionTypes();
@ -98,6 +97,7 @@ $attrTypes = array(
'DiskSpace' => translate('AttrDiskSpace'), 'DiskSpace' => translate('AttrDiskSpace'),
'SystemLoad' => translate('AttrSystemLoad'), 'SystemLoad' => translate('AttrSystemLoad'),
'StorageId' => translate('AttrStorageArea'), 'StorageId' => translate('AttrStorageArea'),
'SecondaryStorageId' => translate('AttrSecondaryStorageArea'),
'ServerId' => translate('AttrMonitorServer'), 'ServerId' => translate('AttrMonitorServer'),
'FilterServerId' => translate('AttrFilterServer'), 'FilterServerId' => translate('AttrFilterServer'),
'MonitorServerId' => translate('AttrMonitorServer'), 'MonitorServerId' => translate('AttrMonitorServer'),
@ -127,27 +127,24 @@ $archiveTypes = array(
$focusWindow = true; $focusWindow = true;
$storageareas = array('' => 'All'); $storageareas = array('' => 'All') + ZM\ZM_Object::Objects_Indexed_By_Id('ZM\Storage');
//$storageareas[0] = 'Default ' . ZM_DIR_EVENTS;
foreach ( dbFetchAll('SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC') as $storage ) {
$storageareas[$storage['Id']] = $storage['Name'];
}
$weekdays = array(); $weekdays = array();
for ( $i = 0; $i < 7; $i++ ) { for ( $i = 0; $i < 7; $i++ ) {
$weekdays[$i] = strftime('%A', mktime(12, 0, 0, 1, $i+1, 2001)); $weekdays[$i] = strftime('%A', mktime(12, 0, 0, 1, $i+1, 2001));
} }
$states = array(); $states = array();
foreach ( dbFetchAll('SELECT Id, Name FROM States ORDER BY lower(Name) ASC') as $state_row ) { foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `States` ORDER BY lower(`Name`) ASC') as $state_row ) {
$states[$state_row['Id']] = validHtmlStr($state_row['Name']); $states[$state_row['Id']] = validHtmlStr($state_row['Name']);
} }
$servers = array(); $servers = array();
$servers['ZM_SERVER_ID'] = 'Current Server'; $servers['ZM_SERVER_ID'] = 'Current Server';
$servers['NULL'] = 'No Server'; $servers['NULL'] = 'No Server';
foreach ( dbFetchAll('SELECT Id, Name FROM Servers ORDER BY lower(Name) ASC') as $server ) { foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `Servers` ORDER BY lower(`Name`) ASC') as $server ) {
$servers[$server['Id']] = validHtmlStr($server['Name']); $servers[$server['Id']] = validHtmlStr($server['Name']);
} }
$monitors = array(); $monitors = array();
foreach ( dbFetchAll('SELECT Id, Name FROM Monitors ORDER BY Name ASC') as $monitor ) { foreach ( dbFetchAll('SELECT `Id`, `Name` FROM `Monitors` ORDER BY lower(`Name`) ASC') as $monitor ) {
if ( visibleMonitor($monitor['Id']) ) { if ( visibleMonitor($monitor['Id']) ) {
$monitors[$monitor['Name']] = validHtmlStr($monitor['Name']); $monitors[$monitor['Name']] = validHtmlStr($monitor['Name']);
} }
@ -273,7 +270,7 @@ for ( $i=0; $i < count($terms); $i++ ) {
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td> <td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $servers, $term['val']); ?></td> <td><?php echo htmlSelect("filter[Query][terms][$i][val]", $servers, $term['val']); ?></td>
<?php <?php
} elseif ( $term['attr'] == 'StorageId' ) { } elseif ( ($term['attr'] == 'StorageId') || ($term['attr'] == 'SecondaryStorageId') ) {
?> ?>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td> <td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $storageareas, $term['val']); ?></td> <td><?php echo htmlSelect("filter[Query][terms][$i][val]", $storageareas, $term['val']); ?></td>
@ -391,7 +388,13 @@ if ( ZM_OPT_MESSAGE ) {
<label><?php echo translate('FilterDeleteEvents') ?></label> <label><?php echo translate('FilterDeleteEvents') ?></label>
<input type="checkbox" name="filter[AutoDelete]" value="1"<?php if ( $filter->AutoDelete() ) { ?> checked="checked"<?php } ?> data-on-click-this="updateButtons"/> <input type="checkbox" name="filter[AutoDelete]" value="1"<?php if ( $filter->AutoDelete() ) { ?> checked="checked"<?php } ?> data-on-click-this="updateButtons"/>
</p> </p>
<p><label><?php echo translate('FilterMoveEvents') ?></label> <p>
<label><?php echo translate('FilterCopyEvents') ?></label>
<input type="checkbox" name="filter[AutoCopy]" value="1"<?php if ( $filter->AutoCopy() ) { ?> checked="checked"<?php } ?> data-on-click-this="click_autocopy"/>
<?php echo htmlSelect('filter[AutoCopyTo]', $storageareas, $filter->AutoCopyTo(), $filter->AutoCopy() ? null : array('style'=>'display:none;')); ?>
</p>
<p>
<label><?php echo translate('FilterMoveEvents') ?></label>
<input type="checkbox" name="filter[AutoMove]" value="1"<?php if ( $filter->AutoMove() ) { ?> checked="checked"<?php } ?> data-on-click-this="click_automove"/> <input type="checkbox" name="filter[AutoMove]" value="1"<?php if ( $filter->AutoMove() ) { ?> checked="checked"<?php } ?> data-on-click-this="click_automove"/>
<?php echo htmlSelect('filter[AutoMoveTo]', $storageareas, $filter->AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;')); ?> <?php echo htmlSelect('filter[AutoMoveTo]', $storageareas, $filter->AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;')); ?>
</p> </p>

View File

@ -72,6 +72,15 @@ function click_automove(element) {
} }
} }
function click_autocopy(element) {
updateButtons(this);
if ( this.checked ) {
$j(this.form.elements['filter[AutoCopyTo]']).css('display', 'inline');
} else {
this.form.elements['filter[AutoCopyTo]'].hide();
}
}
function checkValue( element ) { function checkValue( element ) {
var rows = $j(element).closest('tbody').children(); var rows = $j(element).closest('tbody').children();
parseRows(rows); parseRows(rows);
@ -200,10 +209,10 @@ function parseRows(rows) {
} }
var serverVal = inputTds.eq(4).children().val(); var serverVal = inputTds.eq(4).children().val();
inputTds.eq(4).html(serverSelect).children().val(serverVal).chosen({width: "101%"}); inputTds.eq(4).html(serverSelect).children().val(serverVal).chosen({width: "101%"});
} else if ( attr == 'StorageId' ) { //Choose by storagearea } else if ( (attr == 'StorageId') || (attr == 'SecondaryStorageId') ) { //Choose by storagearea
var storageSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); var storageSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
for ( key in storageareas ) { for ( key in storageareas ) {
storageSelect.append('<option value="' + key + '">' + storageareas[key] + '</option>'); storageSelect.append('<option value="' + key + '">' + storageareas[key].Name + '</option>');
} }
var storageVal = inputTds.eq(4).children().val(); var storageVal = inputTds.eq(4).children().val();
inputTds.eq(4).html(storageSelect).children().val(storageVal).chosen({width: "101%"}); inputTds.eq(4).html(storageSelect).children().val(storageVal).chosen({width: "101%"});