diff --git a/distros/debian/control b/distros/debian/control index 3b11f37b8..ebb59b3ab 100644 --- a/distros/debian/control +++ b/distros/debian/control @@ -17,6 +17,14 @@ Build-Depends: debhelper (>= 9), cmake , libvlccore-dev, libvlc-dev , libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev , libgcrypt11-dev, libpolkit-gobject-1-dev + , libphp-serialization-perl + , libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, libdbd-mysql-perl + , libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl + , libmodule-load-perl, libsys-mmap-perl, libjson-any-perl + , libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl + , libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl + , libsys-cpu-perl, libsys-meminfo-perl + , libdata-uuid-perl Standards-Version: 3.9.4 Package: zoneminder @@ -32,6 +40,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} , libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl , libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl , libsys-cpu-perl, libsys-meminfo-perl + , libdata-uuid-perl , libpcre3 , libav-tools, libavdevice53 , rsyslog | system-log-daemon diff --git a/distros/ubuntu1204/control b/distros/ubuntu1204/control index 6368d9417..d7c2232cf 100644 --- a/distros/ubuntu1204/control +++ b/distros/ubuntu1204/control @@ -5,17 +5,23 @@ Maintainer: Dmitry Smirnov Uploaders: Vagrant Cascadian Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh-linktree ,cmake - ,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev + ,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev ,libbz2-dev ,libgcrypt-dev ,libcurl4-gnutls-dev ,libgnutls-openssl-dev - ,libjpeg8-dev|libjpeg9-dev|libjpeg62-turbo-dev, + ,libjpeg8-dev|libjpeg9-dev|libjpeg62-turbo-dev, ,libmysqlclient-dev ,libpcre3-dev ,libpolkit-gobject-1-dev ,libv4l-dev (>= 0.8.3) [!hurd-any] ,libvlc-dev + ,libdate-manip-perl + ,libdbd-mysql-perl + ,libphp-serialization-perl + ,libsys-mmap-perl [!hurd-any] + ,libwww-perl + ,libdata-uuid-perl # Unbundled (dh_linktree): ,libjs-jquery ,libjs-mootools @@ -37,14 +43,15 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,libmodule-load-conditional-perl ,libnet-sftp-foreign-perl # ,libzoneminder-perl (= ${source:Version}) - ,libarchive-zip-perl - ,libdbd-mysql-perl - ,libdevice-serialport-perl - ,libimage-info-perl - ,libjson-any-perl - ,libsys-mmap-perl [!hurd-any] - ,liburi-encode-perl - ,libwww-perl + ,libarchive-zip-perl + ,libdbd-mysql-perl + ,libdevice-serialport-perl + ,libimage-info-perl + ,libjson-any-perl + ,libsys-mmap-perl [!hurd-any] + ,liburi-encode-perl + ,libwww-perl + ,libdata-uuid-perl ,mysql-client | virtual-mysql-client ,perl-modules ,php5-mysql, php5-gd diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index f16685b5e..c1ee3cc0d 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -25,6 +25,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa ,libphp-serialization-perl ,libsys-mmap-perl [!hurd-any] ,libwww-perl + ,libdata-uuid-perl # Unbundled (dh_linktree): ,libjs-jquery ,libjs-mootools @@ -45,20 +46,21 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,libphp-serialization-perl ,libmodule-load-conditional-perl ,libnet-sftp-foreign-perl - ,libarchive-zip-perl - ,libdbd-mysql-perl - ,libdevice-serialport-perl - ,libimage-info-perl - ,libjson-any-perl - ,libsys-mmap-perl [!hurd-any] - ,liburi-encode-perl - ,libwww-perl - ,libdata-dump-perl - ,libclass-std-fast-perl - ,libsoap-wsdl-perl - ,libio-socket-multicast-perl - ,libdigest-sha-perl - ,libsys-cpu-perl, libsys-meminfo-perl + ,libarchive-zip-perl + ,libdbd-mysql-perl + ,libdevice-serialport-perl + ,libimage-info-perl + ,libjson-any-perl + ,libsys-mmap-perl [!hurd-any] + ,liburi-encode-perl + ,libwww-perl + ,libdata-dump-perl + ,libclass-std-fast-perl + ,libsoap-wsdl-perl + ,libio-socket-multicast-perl + ,libdigest-sha-perl + ,libsys-cpu-perl, libsys-meminfo-perl + ,libdata-uuid-perl ,mysql-client | virtual-mysql-client ,perl-modules ,php5-mysql | php-mysql, php5-gd | php-gd diff --git a/docs/api.rst b/docs/api.rst index 53c6d155b..9546a279a 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -130,6 +130,28 @@ depend on it. curl -XDELETE http://server/zm/api/monitors/1.json +Arm/Disarm monitors +^^^^^^^^^^^^^^^^^^^^ + +This command will force an alarm on Monitor 1: + +:: + + curl http://server/zm/api/monitors/alarm/id:1/command:on.json + +This command will disable the alarm on Monitor 1: + +:: + + curl http://server/zm/api/monitors/alarm/id:1/command:off.json + +This command will report the status of the alarm Monitor 1: + +:: + + curl http://server/zm/api/monitors/alarm/id:1/command:status.json + + Return a list of all events ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -216,6 +238,26 @@ Return a list of events for all monitors within a specified date/time range curl -XGET "http://server/zm/api/events/index/StartTime%20>=:2015-05-15%2018:43:56/EndTime%20<=:208:43:56.json" +Return event count based on times and conditions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The API also supports a handy mechanism to return a count of events for a period of time. + +This returns number of events per monitor that were recorded in the last one hour + +:: + + curl "http://server/zm/api/events/consoleEvents/1%20hour.json" + +This returns number of events per monitor that were recorded in the last day where there were atleast 10 frames that were alarms" + +:: + + curl "http://server/zm/api/events/consoleEvents/1%20day.json/AlarmFrames >=: 10.json" + + + + Configuration Apis ^^^^^^^^^^^^^^^^^^^ diff --git a/onvif/modules/lib/WSDiscovery/TransportUDP.pm b/onvif/modules/lib/WSDiscovery/TransportUDP.pm index 375f9628d..edc837da6 100644 --- a/onvif/modules/lib/WSDiscovery/TransportUDP.pm +++ b/onvif/modules/lib/WSDiscovery/TransportUDP.pm @@ -61,16 +61,19 @@ sub _notify_response } sub send_multi() { - my ($self, $address, $port, $data) = @_; + my ($self, $address, $port, $utf8_string) = @_; my $destination = $address . ':' . $port; my $socket = IO::Socket::Multicast->new(PROTO => 'udp', LocalPort=>$port, PeerAddr=>$destination, ReuseAddr=>1) or die 'Cannot open multicast socket to ' . ${address} . ':' . ${port}; + + my $bytes = $utf8_string; + utf8::encode($bytes); $socket->mcast_ttl(1); - $socket->send($data); + $socket->send($bytes); } sub receive_multi() { diff --git a/onvif/proxy/lib/WSDiscovery10/Elements/Header.pm b/onvif/proxy/lib/WSDiscovery10/Elements/Header.pm new file mode 100644 index 000000000..df2d7f389 --- /dev/null +++ b/onvif/proxy/lib/WSDiscovery10/Elements/Header.pm @@ -0,0 +1,55 @@ + +package WSDiscovery10::Elements::Header; +use strict; +use warnings; + + +__PACKAGE__->_set_element_form_qualified(0); + +sub get_xmlns { 'http://schemas.xmlsoap.org/soap/envelope/' }; + +our $XML_ATTRIBUTE_CLASS; +undef $XML_ATTRIBUTE_CLASS; + +sub __get_attr_class { + return $XML_ATTRIBUTE_CLASS; +} + +use Class::Std::Fast::Storable constructor => 'none'; +use base qw(SOAP::WSDL::XSD::Typelib::ComplexType); + +Class::Std::initialize(); + +{ # BLOCK to scope variables + +my %Action_of :ATTR(:get); +my %MessageID_of :ATTR(:get); +my %ReplyTo_of :ATTR(:get); +my %To_of :ATTR(:get); + +__PACKAGE__->_factory( + [ qw( Action MessageID ReplyTo To ) ], + { + 'Action' => \%Action_of, + 'MessageID' => \%MessageID_of, + 'ReplyTo' => \%ReplyTo_of, + 'To' => \%To_of, + }, + { + 'Action' => 'WSDiscovery10::Elements::Action', + 'MessageID' => 'WSDiscovery10::Elements::MessageID', + 'ReplyTo' => 'WSDiscovery10::Elements::ReplyTo', + 'To' => 'WSDiscovery10::Elements::To', + }, + { + 'Action' => '', + 'MessageID' => '', + 'ReplyTo' => '', + 'To' => '', + } +); + +} # end BLOCK + + +1; diff --git a/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm b/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm index d194bbc87..f1b6446a5 100644 --- a/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm +++ b/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm @@ -34,7 +34,11 @@ sub ProbeOp { }, header => { - + 'use' => 'literal', + namespace => 'http://schemas.xmlsoap.org/ws/2004/08/addressing', + encodingStyle => '', + parts => [qw( WSDiscovery10::Elements::Header )], + }, headerfault => { diff --git a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm index 635a19393..c19a7c647 100644 --- a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm +++ b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm @@ -23,7 +23,12 @@ our $typemap_1 = { 'ProbeMatches/ProbeMatch/Types' => 'WSDiscovery10::Types::QNameListType', 'ProbeMatches/ProbeMatch/EndpointReference' => 'WSDiscovery10::Types::EndpointReferenceType', 'ProbeMatches/ProbeMatch/EndpointReference/ReferenceProperties' => 'WSDiscovery10::Types::ReferencePropertiesType', - 'ProbeMatches/ProbeMatch/EndpointReference/PortType' => 'WSDiscovery10::Types::AttributedQName' + 'ProbeMatches/ProbeMatch/EndpointReference/PortType' => 'WSDiscovery10::Types::AttributedQName', + 'MessageID' => '__SKIP__', + 'RelatesTo' => '__SKIP__', + 'To' => '__SKIP__', + 'Action' => '__SKIP__', + 'AppSequence' => '__SKIP__', }; ; diff --git a/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm b/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm index 10c290e8e..8d7e9e7ca 100644 --- a/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm +++ b/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm @@ -7,8 +7,10 @@ __PACKAGE__->_set_element_form_qualified(0); sub get_xmlns { 'http://schemas.xmlsoap.org/ws/2005/04/discovery' }; -our $XML_ATTRIBUTE_CLASS; -undef $XML_ATTRIBUTE_CLASS; +our $XML_ATTRIBUTE_CLASS = 'WSDiscovery10::Types::ProbeType::_ProbeType::XmlAttr'; + +#our $XML_ATTRIBUTE_CLASS; +#undef $XML_ATTRIBUTE_CLASS; sub __get_attr_class { return $XML_ATTRIBUTE_CLASS; @@ -49,11 +51,55 @@ __PACKAGE__->_factory( } # end BLOCK +package WSDiscovery10::Types::ProbeType::_ProbeType::XmlAttr; +#use base qw(SOAP::WSDL::XSD::Typelib::ComplexType); +use Class::Std::Fast::Storable constructor => 'none', cache => 1; +use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType); +{ # BLOCK to scope variables +my %Attribs_of :ATTR(:get); +sub new +{ + my $self = pop @{ Class::Std::Fast::OBJECT_CACHE_REF()->{ $_[0] } }; + $self = bless \(my $o = Class::Std::Fast::ID()), $_[0] + if not defined $self; + + $self->BUILD(${$self}, $_[1]); + return $self; +} + +sub BUILD +{ + my ($self, $ident, $arg_ref) = @_; + + $Attribs_of{$ident} = $arg_ref; +} + +# without this no attributes are serialized +# SOAP::WSDL::XSD::Typelib::CompexType sub serialize_attr() + +sub as_bool :BOOLIFY { 1 } + +sub serialize() +{ + my $ident = ${ $_[0] }; + my $option_ref = $_[1]; + my $attr_str = ""; + + foreach my $attr (keys %{$Attribs_of{$ident}}) + { + my $value = %{$Attribs_of{$ident}}{$attr}; + $attr_str .= " $attr=\"$value\""; + } + + return $attr_str; +} + +} # end BLOCK 1; diff --git a/onvif/scripts/zmonvif-probe.pl b/onvif/scripts/zmonvif-probe.pl index 93c12959f..10aa26a08 100755 --- a/onvif/scripts/zmonvif-probe.pl +++ b/onvif/scripts/zmonvif-probe.pl @@ -25,13 +25,14 @@ # use Getopt::Std; +use Data::UUID; require ONVIF::Client; require WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort; +require WSDiscovery10::Elements::Header; require WSDiscovery10::Elements::Types; require WSDiscovery10::Elements::Scopes; -require WSDiscovery10::Elements::To; require WSDiscovery::TransportUDP; @@ -169,6 +170,8 @@ sub discover ## try both soap versions my %services; + my $uuid_gen = Data::UUID->new(); + if($verbose) { print "Probing for SOAP 1.1\n" } @@ -177,12 +180,18 @@ sub discover }); $svc_discover->set_soap_version('1.1'); + my $uuid = $uuid_gen->create_str(); + my $result = $svc_discover->ProbeOp( { # WSDiscovery::Types::ProbeType Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType Scopes => { value => '' }, }, - WSDiscovery10::Elements::To->new({ value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }) + WSDiscovery10::Elements::Header->new({ + Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' }, + MessageID => { value => "urn:uuid:$uuid" }, + To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }, + }) ); # print $result . "\n"; @@ -197,12 +206,22 @@ sub discover }); $svc_discover->set_soap_version('1.2'); + # copies of the same Probe message must have the same MessageID. + # This is not a copy. So we generate a new uuid. + $uuid = $uuid_gen->create_str(); + $result = $svc_discover->ProbeOp( { # WSDiscovery::Types::ProbeType - Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType + xmlattr => { 'xmlns:dn' => 'http://www.onvif.org/ver10/network/wsdl', + 'xmlns:tds' => 'http://www.onvif.org/ver10/device/wsdl', }, + Types => 'dn:NetworkVideoTransmitter tds:Device', # QNameListType Scopes => { value => '' }, }, - WSDiscovery10::Elements::To->new({ value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }) + WSDiscovery10::Elements::Header->new({ + Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' }, + MessageID => { value => "urn:uuid:$uuid" }, + To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }, + }) ); # print $result . "\n"; diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 3a226cdc8..0cc8081d2 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -30,6 +30,7 @@ use warnings; require Exporter; require ZoneMinder::Base; +use ZoneMinder::ConfigData qw(:all); our @ISA = qw(Exporter ZoneMinder::Base); @@ -44,7 +45,12 @@ use vars qw( %Config ); our @EXPORT_CONFIG = qw( %Config ); # Get populated by BEGIN our %EXPORT_TAGS = ( - 'constants' => [ qw( + functions => [ qw( + zmConfigLoad + loadConfigFromDB + saveConfigToDB + ) ], + constants => [ qw( ZM_PID ) ] ); @@ -96,20 +102,120 @@ BEGIN } $sth->finish(); #$dbh->disconnect(); +} - if ( ! exists $Config{ZM_SERVER_ID} ) { - $Config{ZM_SERVER_ID} = undef; - $sth = $dbh->prepare_cached( 'SELECT * FROM Servers WHERE Name=?' ); - if ( $Config{ZM_SERVER_NAME} ) { - $res = $sth->execute( $Config{ZM_SERVER_NAME} ); - my $result = $sth->fetchrow_hashref(); - $Config{ZM_SERVER_ID} = $$result{Id}; - } elsif ( $Config{ZM_SERVER_HOST} ) { - $res = $sth->execute( $Config{ZM_SERVER_HOST} ); - my $result = $sth->fetchrow_hashref(); - $Config{ZM_SERVER_ID} = $$result{Id}; - } - } +sub loadConfigFromDB { + print( "Loading config from DB\n" ); + my $dbh = ZoneMinder::Database::zmDbConnect(); + if ( !$dbh ) { + print( "Error: unable to load options from database: $DBI::errstr\n" ); + return( 0 ); + } + my $sql = "select * from Config"; + my $sth = $dbh->prepare_cached( $sql ) + or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() + or croak( "Can't execute: ".$sth->errstr() ); + my $option_count = 0; + while( my $config = $sth->fetchrow_hashref() ) { + my ( $name, $value ) = ( $config->{Name}, $config->{Value} ); +#print( "Name = '$name'\n" ); + my $option = $options_hash{$name}; + if ( !$option ) { + warn( "No option '$name' found, removing" ); + next; + } +#next if ( $option->{category} eq 'hidden' ); + if ( defined($value) ) { + if ( $option->{type} == $types{boolean} ) { + $option->{value} = $value?"yes":"no"; + } else { + $option->{value} = $value; + } + } + $option_count++;; + } + $sth->finish(); + return( $option_count ); +} + +sub saveConfigToDB { + print( "Saving config to DB\n" ); + my $dbh = ZoneMinder::Database::zmDbConnect(); + if ( !$dbh ) + { + print( "Error: unable to save options to database: $DBI::errstr\n" ); + return( 0 ); + } + + my $ac = $dbh->{AutoCommit}; + $dbh->{AutoCommit} = 0; + + $dbh->do('LOCK TABLE Config WRITE') + or croak( "Can't lock Config table: " . $dbh->errstr() ); + + my $sql = "delete from Config"; + my $res = $dbh->do( $sql ) + or croak( "Can't do '$sql': ".$dbh->errstr() ); + + $sql = "replace into Config set Id = ?, Name = ?, Value = ?, Type = ?, DefaultValue = ?, Hint = ?, Pattern = ?, Format = ?, Prompt = ?, Help = ?, Category = ?, Readonly = ?, Requires = ?"; + my $sth = $dbh->prepare_cached( $sql ) + or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + foreach my $option ( @options ) + { +#next if ( $option->{category} eq 'hidden' ); +#print( $option->{name}."\n" ) if ( !$option->{category} ); + $option->{db_type} = $option->{type}->{db_type}; + $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" + ; + } + else + { + $option->{db_value} = $option->{value}; + } + if ( my $requires = $option->{requires} ) + { + $option->{db_requires} = join( ";", + map { + my $value = $_->{value}; + $value = ($value eq "yes") + ? 1 + : 0 + if ( $options_hash{$_->{name}}->{db_type} eq "boolean" ) + ; ( "$_->{name}=$value" ) + } @$requires + ); + } + else + { + } + my $res = $sth->execute( + $option->{id}, + $option->{name}, + $option->{db_value}, + $option->{db_type}, + $option->{default}, + $option->{db_hint}, + $option->{db_pattern}, + $option->{db_format}, + $option->{description}, + $option->{help}, + $option->{category}, + $option->{readonly} ? 1 : 0, + $option->{db_requires} + ) or croak( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + + $dbh->do('UNLOCK TABLES'); + $dbh->{AutoCommit} = $ac; } 1; @@ -121,7 +227,7 @@ ZoneMinder::Config - ZoneMinder configuration module. =head1 SYNOPSIS - use ZoneMinder::Config qw(:all); +use ZoneMinder::Config qw(:all); =head1 DESCRIPTION @@ -136,7 +242,25 @@ namespace of the calling program or module. Once the configuration has been imported then configuration variables are defined as constants and can be accessed directory by name, e.g. - $lang = $Config{ZM_LANG_DEFAULT}; +$lang = $Config{ZM_LANG_DEFAULT}; + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with +the definitions held in this module. This results in the merging of any new +configuration and the removal of any deprecated configuration while +preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and +saving configuration is a convenient way to ensure that the configuration +held in the database corresponds with the most recent definitions and that +all components are using the same set of configuration. =head2 EXPORT @@ -159,7 +283,7 @@ Copyright (C) 2001-2008 Philip Coombes This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, -at your option, any later version of Perl 5 you may have available. + at your option, any later version of Perl 5 you may have available. -=cut + =cut diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index fc4143d8a..610d2432d 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -1709,6 +1709,17 @@ our @options = type => $types{boolean}, category => "config", }, + { + name => 'ZM_LD_PRELOAD', + default => '', + description => "Path to library to preload before launching daemons", + help => qqq("Some older cameras require the use of the v4l1 compat + library. This setting allows the setting of the path + to the library, so that it can be loaded by zmdc.pl + before launching zmc."), + type => $types{abs_path}, + category => 'config', + }, { name => "ZM_SIGNAL_CHECK_POINTS", default => "10", diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in index 36d5e922a..e70c4d568 100644 --- a/scripts/zmdc.pl.in +++ b/scripts/zmdc.pl.in @@ -75,6 +75,10 @@ $| = 1; $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +if ( $Config{ZM_LD_PRELOAD} ) { + Debug("Adding ENV{LD_PRELOAD} = $Config{ZM_LD_PRELOAD}"); + $ENV{LD_PRELOAD} = $Config{ZM_LD_PRELOAD}; +} delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my @daemons = ( @@ -88,7 +92,7 @@ my @daemons = ( 'zmwatch.pl', 'zmupdate.pl', 'zmtrack.pl', - 'zmtelemetry.pl', + 'zmtelemetry.pl' ); my $command = shift @ARGV; diff --git a/scripts/zmtelemetry.pl.in b/scripts/zmtelemetry.pl.in index c7bf4a3f3..5a5328829 100644 --- a/scripts/zmtelemetry.pl.in +++ b/scripts/zmtelemetry.pl.in @@ -71,7 +71,7 @@ if ( $Config{ZM_TELEMETRY_DATA} ) { print( "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); - my $lastCheck = $Config{ZM_TELEMETRY_LAST_CHECK}; + my $lastCheck = $Config{ZM_TELEMETRY_LAST_UPLOAD}; while( 1 ) { my $now = time(); diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index 3143b2d50..ccc76ba02 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -155,6 +155,7 @@ if ( $check && $Config{ZM_CHECK_FOR_UPDATES} ) my $sql = "update Config set Value = ? where Name = 'ZM_DYN_CURR_VERSION'"; my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute( "$currVersion" ) or die( "Can't execute: ".$sth->errstr() ); + $sth->finish(); } while( 1 ) @@ -184,10 +185,12 @@ if ( $check && $Config{ZM_CHECK_FOR_UPDATES} ) my $lv_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_VERSION'"; my $lv_sth = $dbh->prepare_cached( $lv_sql ) or die( "Can't prepare '$lv_sql': ".$dbh->errstr() ); my $lv_res = $lv_sth->execute( $lastVersion ) or die( "Can't execute: ".$lv_sth->errstr() ); + $lv_sth->finish(); my $lc_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_CHECK'"; my $lc_sth = $dbh->prepare_cached( $lc_sql ) or die( "Can't prepare '$lc_sql': ".$dbh->errstr() ); my $lc_res = $lc_sth->execute( $lastCheck ) or die( "Can't execute: ".$lc_sth->errstr() ); + $lc_sth->finish(); } else { @@ -239,14 +242,14 @@ if ( $zoneFix ) } $sth->finish(); + $sql = "update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); foreach my $zone ( @zones ) { my $zone_width = (($zone->{HiX}*$zone->{MonitorWidth})-($zone->{LoX}*$zone->{MonitorWidth}))/100; my $zone_height = (($zone->{HiY}*$zone->{MonitorHeight})-($zone->{LoY}*$zone->{MonitorHeight}))/100; my $zone_area = $zone_width * $zone_height; my $monitor_area = $zone->{MonitorWidth} * $zone->{MonitorHeight}; - my $sql = "update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?"; - my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute( ($zone->{MinAlarmPixels}*$monitor_area)/$zone_area, ($zone->{MaxAlarmPixels}*$monitor_area)/$zone_area, @@ -257,6 +260,7 @@ if ( $zoneFix ) $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() ); } + $sth->finish(); } if ( $migrateEvents ) { @@ -318,11 +322,13 @@ if ( $migrateEvents ) symlink( $newTimePath, $idLink ) or die( "Can't symlink $newTimePath -> $idLink: $!" ); rename( $oldEventPath, $newEventPath ) or die( "Can't move $oldEventPath -> $newEventPath: $!" ); } + $sth->finish(); print( "Updating configuration.\n" ); $sql = "update Config set Value = ? where Name = 'ZM_USE_DEEP_STORAGE'"; $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); $res = $sth->execute( 1 ) or die( "Can't execute: ".$sth->errstr() ); + $sth->finish(); print( "All events converted.\n\n" ); } @@ -334,8 +340,8 @@ if ( $migrateEvents ) if ( $freshen ) { print( "\nFreshening configuration in database\n" ); - loadConfigFromDB(); - saveConfigToDB(); + ZoneMinder::Config::loadConfigFromDB(); + ZoneMinder::Config::saveConfigToDB(); } # Don't do innoDB upgrade if not interactive @@ -360,10 +366,10 @@ if ( $interactive ) { $dbh->do(q|SET sql_mode='traditional'|); # Elevate warnings to errors print "\nConverting MyISAM tables to InnoDB. Please wait.\n"; foreach (@MyISAM_Tables) { - my $sql = "ALTER TABLE $_ ENGINE = InnoDB"; - my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $sql = "ALTER TABLE $_ ENGINE = InnoDB"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); - $sth->finish(); + $sth->finish(); } $dbh->do(q|SET sql_mode=''|); # Set mode back to default } @@ -494,8 +500,8 @@ if ( $version ) print( "\nUpgrading database to version ".ZM_VERSION."\n" ); # Update config first of all - loadConfigFromDB(); - saveConfigToDB(); + ZoneMinder::Config::loadConfigFromDB(); + ZoneMinder::Config::saveConfigToDB(); my $cascade = undef; if ( $cascade || $version eq "1.19.0" ) @@ -1064,6 +1070,7 @@ if ( $version ) my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute( "$installed_version", "ZM_DYN_DB_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); $res = $sth->execute( "$installed_version", "ZM_DYN_CURR_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); + $sth->finish(); } else { diff --git a/src/zm_rtp_ctrl.h b/src/zm_rtp_ctrl.h index 2526f22ce..f487d1191 100644 --- a/src/zm_rtp_ctrl.h +++ b/src/zm_rtp_ctrl.h @@ -123,7 +123,7 @@ private: } sdes; // BYE - struct Bye + struct { uint32_t srcN[]; // list of sources // can't express trailing text for reason (what does this mean? it's not even english!) diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index 3bab38f86..8c89c33b6 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -291,18 +291,21 @@ void StreamBase::openComms() if ( connkey > 0 ) { - snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", config.path_socks, connkey); + unsigned int length = snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", config.path_socks, connkey); + if ( length >= sizeof(sock_path_lock) ) { + Warning("Socket lock path was truncated."); + length = sizeof(sock_path_lock)-1; + } lock_fd = open(sock_path_lock, O_CREAT|O_WRONLY, S_IRUSR | S_IWUSR); if ( lock_fd <= 0 ) - { + { Error("Unable to open sock lock file %s: %s", sock_path_lock, strerror(errno) ); lock_fd = 0; - } - else if ( flock(lock_fd, LOCK_EX) != 0 ) + } + else if ( flock(lock_fd, LOCK_EX) != 0 ) { Error("Unable to lock sock lock file %s: %s", sock_path_lock, strerror(errno) ); - close(lock_fd); lock_fd = 0; } @@ -311,19 +314,25 @@ void StreamBase::openComms() Debug( 1, "We have obtained a lock on %s fd: %d", sock_path_lock, lock_fd); } - sd = socket( AF_UNIX, SOCK_DGRAM, 0 ); if ( sd < 0 ) { Fatal( "Can't create socket: %s", strerror(errno) ); } - snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey ); + length = snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey ); + if ( length >= sizeof(loc_sock_path) ) { + Warning("Socket path was truncated."); + length = sizeof(loc_sock_path)-1; + } unlink( loc_sock_path ); + if ( sizeof(loc_addr.sun_path) < length ) { + Error("Not enough space %d in loc_addr.sun_path for socket file %s", sizeof(loc_addr.sun_path), loc_sock_path ); + } strncpy( loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path) ); loc_addr.sun_family = AF_UNIX; - if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)) < 0 ) + if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family))+1 < 0 ) { Fatal( "Can't bind: %s", strerror(errno) ); } @@ -331,7 +340,7 @@ void StreamBase::openComms() snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", config.path_socks, connkey ); strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) ); rem_addr.sun_family = AF_UNIX; - } + } // end if connKey > 0 } void StreamBase::closeComms() diff --git a/web/ajax/alarm.php b/web/ajax/alarm.php index b1f5f1496..2d4690866 100644 --- a/web/ajax/alarm.php +++ b/web/ajax/alarm.php @@ -1,5 +1,4 @@ diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index e6d841c9f..7bf36de75 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -103,7 +103,7 @@ public function beforeFilter() { $this->Monitor->create(); if ($this->Monitor->save($this->request->data)) { - $this->daemonControl($this->Monitor->id, 'start', $this->request->data); + $this->daemonControl($this->Monitor->id, 'start'); return $this->flash(__('The monitor has been saved.'), array('action' => 'index')); } } @@ -138,8 +138,8 @@ public function beforeFilter() { '_serialize' => array('message') )); // - restart this monitor after change - // We don't pass the request data as the monitor object because it may be a subset of the full monitor array - $this->daemonControl( $this->Monitor->id, 'restart' ); + // We don't pass the request data as the monitor object because it may be a subset of the full monitor array + $this->daemonControl( $this->Monitor->id, 'restart' ); } /** @@ -187,7 +187,7 @@ public function beforeFilter() { // arm/disarm alarms // expected format: http(s):/portal-api-url/monitors/alarm/id:M/command:C.json // where M=monitorId - // where C=on|off + // where C=on|off|status public function alarm() { $id = $this->request->params['named']['id']; @@ -195,19 +195,27 @@ public function beforeFilter() { if (!$this->Monitor->exists($id)) { throw new NotFoundException(__('Invalid monitor')); } - if ( $cmd != 'on' && $cmd != 'off') + if ( $cmd != 'on' && $cmd != 'off' && $cmd != 'status') { throw new BadRequestException(__('Invalid command')); } - - if ($this->Session->Read('systemPermission') != 'Edit') - { - throw new UnauthorizedException(__('Insufficient privileges')); - return; - } - $zm_path_bin = Configure::read('ZM_PATH_BIN'); - $q = ($cmd == 'on') ? '-a':'-c'; + + switch ($cmd) + { + case "on": + $q = '-a'; + $verbose = "-v"; + break; + case "off": + $q = "-c"; + $verbose = "-v"; + break; + case "status": + $verbose = ""; // zmu has a bug - gives incorrect verbose output in this case + $q = "-s"; + break; + } // form auth key based on auth credentials $this->loadModel('Config'); @@ -245,7 +253,7 @@ public function beforeFilter() { } } - $shellcmd = escapeshellcmd("$zm_path_bin/zmu -v -m$id $q $auth"); + $shellcmd = escapeshellcmd("$zm_path_bin/zmu $verbose -m$id $q $auth"); $status = exec ($shellcmd); $this->set(array( diff --git a/web/api/app/Controller/ServersController.php b/web/api/app/Controller/ServersController.php new file mode 100644 index 000000000..88a5bec90 --- /dev/null +++ b/web/api/app/Controller/ServersController.php @@ -0,0 +1,155 @@ +Session->Read('streamPermission'); + if ($canView =='None') { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } + +} + + +/** + * index method + * + * @return void + */ + public function index() { + $this->Server->recursive = 0; + + $options=''; + $servers = $this->Server->find('all',$options); + $this->set(array( + 'servers' => $servers, + '_serialize' => array('servers') + )); + } + +/** + * view method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function view($id = null) { + $this->Server->recursive = 0; + if (!$this->Server->exists($id)) { + throw new NotFoundException(__('Invalid server')); + } + $restricted = ''; + + $options = array('conditions' => array( + array('Server.' . $this->Server->primaryKey => $id), + $restricted + ) + ); + $server = $this->Server->find('first', $options); + $this->set(array( + 'server' => $server, + '_serialize' => array('server') + )); + } + +/** + * add method + * + * @return void + */ + public function add() { + if ($this->request->is('post')) { + + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + + $this->Server->create(); + if ($this->Server->save($this->request->data)) { + # Might be nice to send it a start request + #$this->daemonControl($this->Server->id, 'start', $this->request->data); + return $this->flash(__('The server has been saved.'), array('action' => 'index')); + } + } + } + +/** + * edit method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function edit($id = null) { + $this->Server->id = $id; + + if (!$this->Server->exists($id)) { + throw new NotFoundException(__('Invalid server')); + } + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + if ($this->Server->save($this->request->data)) { + $message = 'Saved'; + } else { + $message = 'Error'; + } + + $this->set(array( + 'message' => $message, + '_serialize' => array('message') + )); + // - restart this server after change + #$this->daemonControl($this->Server->id, 'restart', $this->request->data); + } + +/** + * delete method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function delete($id = null) { + $this->Server->id = $id; + if (!$this->Server->exists()) { + throw new NotFoundException(__('Invalid server')); + } + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + $this->request->allowMethod('post', 'delete'); + + #$this->daemonControl($this->Server->id, 'stop'); + + if ($this->Server->delete()) { + return $this->flash(__('The server has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The server could not be deleted. Please, try again.'), array('action' => 'index')); + } + } +} diff --git a/web/api/app/Model/Server.php b/web/api/app/Model/Server.php new file mode 100644 index 000000000..b58450db5 --- /dev/null +++ b/web/api/app/Model/Server.php @@ -0,0 +1,74 @@ + array( + 'numeric' => array( + 'rule' => array('numeric'), + //'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 + ), + ), + ); + + //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', + 'foreignKey' => 'ServerId', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); +} diff --git a/web/api/app/View/Servers/json/edit.ctp b/web/api/app/View/Servers/json/edit.ctp new file mode 100644 index 000000000..0be859571 --- /dev/null +++ b/web/api/app/View/Servers/json/edit.ctp @@ -0,0 +1,2 @@ +echo json_encode($message); +echo json_encode($server); diff --git a/web/api/app/View/Servers/json/index.ctp b/web/api/app/View/Servers/json/index.ctp new file mode 100644 index 000000000..6e5cbd26d --- /dev/null +++ b/web/api/app/View/Servers/json/index.ctp @@ -0,0 +1 @@ +echo json_encode($servers); diff --git a/web/api/app/View/Servers/json/view.ctp b/web/api/app/View/Servers/json/view.ctp new file mode 100644 index 000000000..c3d0226ab --- /dev/null +++ b/web/api/app/View/Servers/json/view.ctp @@ -0,0 +1 @@ +echo json_encode($server); diff --git a/web/api/app/View/Servers/xml/edit.ctp b/web/api/app/View/Servers/xml/edit.ctp new file mode 100644 index 000000000..09fb8979a --- /dev/null +++ b/web/api/app/View/Servers/xml/edit.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $message)); +echo $xml->asXML(); diff --git a/web/api/app/View/Servers/xml/index.ctp b/web/api/app/View/Servers/xml/index.ctp new file mode 100644 index 000000000..37afc918b --- /dev/null +++ b/web/api/app/View/Servers/xml/index.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $monitors)); +echo $xml->asXML(); diff --git a/web/api/app/View/Servers/xml/view.ctp b/web/api/app/View/Servers/xml/view.ctp new file mode 100644 index 000000000..b33c6e79a --- /dev/null +++ b/web/api/app/View/Servers/xml/view.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $monitor)); +echo $xml->asXML(); diff --git a/web/includes/Event.php b/web/includes/Event.php new file mode 100644 index 000000000..5ad1c4031 --- /dev/null +++ b/web/includes/Event.php @@ -0,0 +1,152 @@ + $v) { + $this->{$k} = $v; + } + } else { + Error("No row for Event " . $IdOrRow ); + } + } // end function __construct + public function Storage() { + return new Storage( $this->{'StorageId'} ); + } + public function __call( $fn, array $args){ + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); + } + } + + public function Time() { + if ( ! isset( $this->{'Time'} ) ) { + $this->{'Time'} = strtotime($this->{'StartTime'}); + } + return $this->{'Time'}; + } + + public function Path() { + $Storage = $this->Storage(); + return $Storage->Path().'/'.$this->Relative_Path(); + } + public function Relative_Path() { + $event_path = ""; + + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = + $this->{'MonitorId'} + .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $this->Time() + ) + ; + } + else + { + $event_path = + $this->{'MonitorId'} + .'/'.$this->{'Id'} + ; + } + + return( $event_path ); + + } + + public function LinkPath() { + if ( ZM_USE_DEEP_STORAGE ) { + return $this->{'MonitorId'} .'/'.strftime( "%y/%m/%d/.", $this->Time()).$this->{'Id'}; + } + Error("Calling Link_Path when not using deep storage"); + return ''; + } + + public function delete() { + dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) ); + if ( !ZM_OPT_FAST_DELETE ) { + dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) ); + dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}) ); + if ( ZM_USE_DEEP_STORAGE ) { + +# Assumption: All events haev a start time + $start_date = date_parse( $this->{'StartTime'} ); + $start_date['year'] = $start_date['year'] % 100; + + $Storage = $this->Storage(); +# So this is because ZM creates a link under teh day pointing to the time that the event happened. + $eventlink_path = $Storage->Path().'/'.$this->Link_Path(); + + if ( $id_files = glob( $eventlink_path ) ) { +# I know we are using arrays here, but really there can only ever be 1 in the array + $eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] ); + deletePath( $eventPath ); + deletePath( $id_files[0] ); + $pathParts = explode( '/', $eventPath ); + for ( $i = count($pathParts)-1; $i >= 2; $i-- ) { + $deletePath = join( '/', array_slice( $pathParts, 0, $i ) ); + if ( !glob( $deletePath."/*" ) ) { + deletePath( $deletePath ); + } + } + } else { + Warning( "Found no event files under $eventlink_path" ); + } # end if found files + } else { + $eventPath = $this->Path(); + deletePath( $eventPath ); + } # USE_DEEP_STORAGE OR NOT + } # ! ZM_OPT_FAST_DELETE + } # end Event->delete + +public function getStreamSrc( $args, $querySep='&' ) { + return ZM_BASE_URL.'/index.php?view=view_video&eid='.$this->{'Id'}; + + $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; + + $args[] = "source=event&event=".$this->{'Id'}; + + if ( ZM_OPT_USE_AUTH ) { + if ( ZM_AUTH_RELAY == "hashed" ) { + $args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS ); + } elseif ( ZM_AUTH_RELAY == "plain" ) { + $args[] = "user=".$_SESSION['username']; + $args[] = "pass=".$_SESSION['password']; + } elseif ( ZM_AUTH_RELAY == "none" ) { + $args[] = "user=".$_SESSION['username']; + } + } + if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) { + $args[] = "connkey=".$GLOBALS['connkey']; + } + if ( ZM_RAND_STREAM ) { + $args[] = "rand=".time(); + } + + if ( count($args) ) { + $streamSrc .= "?".join( $querySep, $args ); + } + + return( $streamSrc ); + } // end function getStreamSrc +} # end class +?> diff --git a/web/includes/Frame.php b/web/includes/Frame.php new file mode 100644 index 000000000..5973cd1bf --- /dev/null +++ b/web/includes/Frame.php @@ -0,0 +1,103 @@ + $v) { + $this->{$k} = $v; + } + } else { + Error("No row for Frame " . $IdOrRow ); + } + } // end function __construct + public function Storage() { + return $this->Event()->Storage(); + } + public function Event() { + return new Event( $this->{'EventId'} ); + } + public function __call( $fn, array $args){ + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); + } + } + + public function Path() { + $Storage = $this->Storage(); + return $Storage->Path().'/'.$this->Relative_Path(); + } + public function Relative_Path() { + $event_path = ""; + + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = + $this->{'MonitorId'} + .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $this->Time() + ) + ; + } + else + { + $event_path = + $this->{'MonitorId'} + .'/'.$this->{'Id'} + ; + } + + return( $event_path ); + + } + + public function getImageSrc( ) { + return ZM_BASE_URL.'/index.php?view=image&fid='.$this->{'Id'}; + } // end function getImageSrc + + public static function find( $parameters = array(), $limit = NULL ) { + $sql = 'SELECT * FROM Frames'; + $values = array(); + if ( sizeof($parameters) ) { + $sql .= ' WHERE ' . implode( ' AND ', array_map( + function($v){ return $v.'=?'; }, + array_keys( $parameters ) + ) ); + $values = array_values( $parameters ); + } + if ( $limit ) { + $sql .= ' LIMIT ' . $limit; + } + $results = dbFetchAll( $sql, NULL, $values ); + if ( $results ) { + return array_map( function($id){ return new Frame($id); }, $results ); + } + } + + public static function find_one( $parameters = array() ) { + $results = Frame::find( $parameters, 1 ); + if ( ! sizeof( $results ) ) { + return; + } + return $results[0]; + } +} # end class +?> diff --git a/web/includes/Server.php b/web/includes/Server.php index e8402809c..dfce67eb8 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -1,28 +1,28 @@ $v) { - $this->{$k} = $v; - } - } else { - $this->{'Name'} = ''; - $this->{'Hostname'} = ''; - } +class Server { + public function __construct( $IdOrRow = NULL ) { + $row = NULL; + if ( $IdOrRow ) { + if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { + $row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) ); + if ( ! $row ) { + Error("Unable to load Server record for Id=" . $IdOrRow ); + } + } elseif ( is_array( $IdOrRow ) ) { + $row = $IdOrRow; + } + } # end if isset($IdOrRow) + if ( $row ) { + foreach ($row as $k => $v) { + $this->{$k} = $v; + } + } else { + $this->{'Name'} = ''; + $this->{'Hostname'} = ''; } + } public static function find_all() { $servers = array(); $result = dbQuery( 'SELECT * FROM Servers ORDER BY Name'); @@ -47,11 +47,38 @@ class Server { return $this->{'Name'}; } public function __call( $fn, array $args= NULL){ - if(isset($this->{$fn})){ - return $this->{$fn}; - #array_unshift($args, $this); - #call_user_func_array( $this->{$fn}, $args); - } + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); } + } + public static function find( $parameters = array(), $limit = NULL ) { + $sql = 'SELECT * FROM Servers'; + $values = array(); + if ( sizeof($parameters) ) { + $sql .= ' WHERE ' . implode( ' AND ', array_map( + function($v){ return $v.'=?'; }, + array_keys( $parameters ) + ) ); + $values = array_values( $parameters ); + } + if ( $limit ) { + $sql .= ' LIMIT ' . $limit; + } + $results = dbFetchAll( $sql, NULL, $values ); + if ( $results ) { + return array_map( function($id){ return new Server($id); }, $results ); + } + } + + public static function find_one( $parameters = array() ) { + $results = Server::find( $parameters, 1 ); + if ( ! sizeof( $results ) ) { + return; + } + return $results[0]; + } + } ?> diff --git a/web/includes/Storage.php b/web/includes/Storage.php new file mode 100644 index 000000000..546cb9cbe --- /dev/null +++ b/web/includes/Storage.php @@ -0,0 +1,51 @@ + $v) { + $this->{$k} = $v; + } + } else { + $this->{'Name'} = ''; + $this->{'Path'} = ''; + } + } + + public function Path() { + if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) { + return $this->{'Path'}; + } else if ( ! isset($this->{'Id'}) ) { + return ZM_DIR_EVENTS; + } + return $this->{'Name'}; + } + public function __call( $fn, array $args= NULL){ + if(isset($this->{$fn})){ + return $this->{$fn}; + #array_unshift($args, $this); + #call_user_func_array( $this->{$fn}, $args); + } + } + public static function find_all() { + $storage_areas = array(); + $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name'); + $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' ); + foreach ( $results as $row => $obj ) { + $storage_areas[] = $obj; + } + return $storage_areas; + } +} +?> diff --git a/web/includes/functions.php b/web/includes/functions.php index 459a3772d..25f7edd46 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -19,214 +19,175 @@ // // Compatibility functions -if ( version_compare( phpversion(), "4.3.0", "<") ) -{ - function ob_get_clean() - { - $buffer = ob_get_contents(); - ob_end_clean(); - return( $buffer ); - } +if ( version_compare( phpversion(), "4.3.0", "<") ) { + function ob_get_clean() { + $buffer = ob_get_contents(); + ob_end_clean(); + return( $buffer ); + } } -function userLogin( $username, $password="", $passwordHashed=false ) -{ - global $user, $cookies; +function userLogin( $username, $password="", $passwordHashed=false ) { + global $user, $cookies; - $sql = "select * from Users where Enabled = 1"; - $sql_values = NULL; - if ( ZM_AUTH_TYPE == "builtin" ) - { - if ( $passwordHashed ) { - $sql .= " AND Username=? AND Password=?"; - } else { - $sql .= " AND Username=? AND Password=password(?)"; - } - $sql_values = array( $username, $password ); + $sql = "select * from Users where Enabled = 1"; + $sql_values = NULL; + if ( ZM_AUTH_TYPE == "builtin" ) { + if ( $passwordHashed ) { + $sql .= " AND Username=? AND Password=?"; } else { - $sql .= " AND Username = ?"; - $sql_values = array( $username ); + $sql .= " AND Username=? AND Password=password(?)"; } - $_SESSION['username'] = $username; - if ( ZM_AUTH_RELAY == "plain" ) - { - // Need to save this in session - $_SESSION['password'] = $password; + $sql_values = array( $username, $password ); + } else { + $sql .= " AND Username = ?"; + $sql_values = array( $username ); + } + $_SESSION['username'] = $username; + if ( ZM_AUTH_RELAY == "plain" ) { + // Need to save this in session + $_SESSION['password'] = $password; + } + $_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking + if ( $dbUser = dbFetchOne( $sql, NULL, $sql_values ) ) { + Info( "Login successful for user \"$username\"" ); + $_SESSION['user'] = $user = $dbUser; + if ( ZM_AUTH_TYPE == "builtin" ) { + $_SESSION['passwordHash'] = $user['Password']; } - $_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking - if ( $dbUser = dbFetchOne( $sql, NULL, $sql_values ) ) - { - Info( "Login successful for user \"$username\"" ); - $_SESSION['user'] = $user = $dbUser; - if ( ZM_AUTH_TYPE == "builtin" ) - { - $_SESSION['passwordHash'] = $user['Password']; - } - } - else - { - Warning( "Login denied for user \"$username\"" ); - unset( $user ); - } - if ( $cookies ) - session_write_close(); -} - -function userLogout() -{ - global $user; - $username = $user['Username']; - - Info( "User \"$username\" logged out" ); - - unset( $_SESSION['user'] ); + } else { + Warning( "Login denied for user \"$username\"" ); unset( $user ); - - session_destroy(); + } + if ( $cookies ) + session_write_close(); } -function noCacheHeaders() -{ - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past - header("Last-Modified: ".gmdate( "D, d M Y H:i:s" )." GMT"); // always modified - header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); // HTTP/1.0 +function userLogout() { + global $user; + $username = $user['Username']; + + Info( "User \"$username\" logged out" ); + + unset( $_SESSION['user'] ); + unset( $user ); + + session_destroy(); +} + +function noCacheHeaders() { + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past + header("Last-Modified: ".gmdate( "D, d M Y H:i:s" )." GMT"); // always modified + header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); // HTTP/1.0 } function CORSHeaders() { - if ( isset( $_SERVER['HTTP_ORIGIN'] ) ) { + if ( isset( $_SERVER['HTTP_ORIGIN'] ) ) { - # The following is left for future reference/use. - $valid = false; - $servers = dbFetchAll( 'SELECT * FROM Servers' ); - if ( sizeof($servers) <= 1 ) { - # Only need CORSHeaders in the event that there are multiple servers in use. - return; - } - foreach( dbFetchAll( 'SELECT * FROM Servers' ) as $row ) { - $Server = new Server( $row ); - if ( $_SERVER['HTTP_ORIGIN'] == $Server->Url() ) { - $valid = true; - header("Access-Control-Allow-Origin: " . $Server->Url() ); - header("Access-Control-Allow-Headers: x-requested-with,x-request"); - } - } - if ( ! $valid ) { - Warning( $_SERVER['HTTP_ORIGIN'] . " is not found in servers list." ); - } - } +# The following is left for future reference/use. + $valid = false; + $servers = dbFetchAll( 'SELECT * FROM Servers' ); + if ( sizeof($servers) <= 1 ) { +# Only need CORSHeaders in the event that there are multiple servers in use. + return; + } + foreach( dbFetchAll( 'SELECT * FROM Servers' ) as $row ) { + $Server = new Server( $row ); + if ( $_SERVER['HTTP_ORIGIN'] == $Server->Url() ) { + $valid = true; + header("Access-Control-Allow-Origin: " . $Server->Url() ); + header("Access-Control-Allow-Headers: x-requested-with,x-request"); + } + } + if ( ! $valid ) { + Warning( $_SERVER['HTTP_ORIGIN'] . " is not found in servers list." ); + } + } } -function getAuthUser( $auth ) -{ - if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" && !empty($auth) ) - { +function getAuthUser( $auth ) { + if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" && !empty($auth) ) { + $remoteAddr = ""; + if ( ZM_AUTH_HASH_IPS ) { + $remoteAddr = $_SERVER['REMOTE_ADDR']; + if ( !$remoteAddr ) { + Error( "Can't determine remote address for authentication, using empty string" ); $remoteAddr = ""; - if ( ZM_AUTH_HASH_IPS ) - { - $remoteAddr = $_SERVER['REMOTE_ADDR']; - if ( !$remoteAddr ) - { - Error( "Can't determine remote address for authentication, using empty string" ); - $remoteAddr = ""; - } - } - - $sql = "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1"; - foreach ( dbFetchAll( $sql ) as $user ) - { - $now = time(); - for ( $i = 0; $i < 2; $i++, $now -= (60*60) ) // Try for last two hours - { - $time = localtime( $now ); - $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5]; - $authHash = md5( $authKey ); - - if ( $auth == $authHash ) - { - return( $user ); - } - } - } + } } - Error( "Unable to authenticate user from auth hash '$auth'" ); - return( false ); + + $sql = "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1"; + foreach ( dbFetchAll( $sql ) as $user ) { + $now = time(); + for ( $i = 0; $i < 2; $i++, $now -= (60*60) ) { // Try for last two hours + $time = localtime( $now ); + $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5]; + $authHash = md5( $authKey ); + + if ( $auth == $authHash ) { + return( $user ); + } + } + } + } + Error( "Unable to authenticate user from auth hash '$auth'" ); + return( false ); } -function generateAuthHash( $useRemoteAddr ) -{ - if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) - { - $time = localtime(); - if ( $useRemoteAddr ) - { - $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$time[2].$time[3].$time[4].$time[5]; - } - else - { - $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$time[2].$time[3].$time[4].$time[5]; - } - $auth = md5( $authKey ); +function generateAuthHash( $useRemoteAddr ) { + if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) { + $time = localtime(); + if ( $useRemoteAddr ) { + $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$time[2].$time[3].$time[4].$time[5]; + } else { + $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$time[2].$time[3].$time[4].$time[5]; } - else - { - $auth = ""; - } - return( $auth ); + $auth = md5( $authKey ); + } else { + $auth = ""; + } + return( $auth ); } -function getStreamSrc( $args, $querySep='&' ) -{ - $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; +function getStreamSrc( $args, $querySep='&' ) { + $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; - if ( ZM_OPT_USE_AUTH ) - { - if ( ZM_AUTH_RELAY == "hashed" ) - { - $args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS ); - } - elseif ( ZM_AUTH_RELAY == "plain" ) - { - $args[] = "user=".$_SESSION['username']; - $args[] = "pass=".$_SESSION['password']; - } - elseif ( ZM_AUTH_RELAY == "none" ) - { - $args[] = "user=".$_SESSION['username']; - } - } - if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) - { - $args[] = "connkey=".$GLOBALS['connkey']; - } - if ( ZM_RAND_STREAM ) - { - $args[] = "rand=".time(); + if ( ZM_OPT_USE_AUTH ) { + if ( ZM_AUTH_RELAY == "hashed" ) { + $args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS ); + } elseif ( ZM_AUTH_RELAY == "plain" ) { + $args[] = "user=".$_SESSION['username']; + $args[] = "pass=".$_SESSION['password']; + } elseif ( ZM_AUTH_RELAY == "none" ) { + $args[] = "user=".$_SESSION['username']; } + } + if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) { + $args[] = "connkey=".$GLOBALS['connkey']; + } + if ( ZM_RAND_STREAM ) { + $args[] = "rand=".time(); + } - if ( count($args) ) - { - $streamSrc .= "?".join( $querySep, $args ); - } + if ( count($args) ) { + $streamSrc .= "?".join( $querySep, $args ); + } - return( $streamSrc ); + return( $streamSrc ); } -function getMimeType( $file ) -{ - if ( function_exists('mime_content_type') ) - { - return( mime_content_type( $file ) ); - } - elseif ( function_exists('finfo_file') ) - { - $finfo = finfo_open( FILEINFO_MIME ); - $mimeType = finfo_file( $finfo, $file ); - finfo_close($finfo); - return( $mimeType ); - } - return( trim( exec( 'file -bi '.escapeshellarg( $file ).' 2>/dev/null' ) ) ); +function getMimeType( $file ) { + if ( function_exists('mime_content_type') ) { + return( mime_content_type( $file ) ); + } elseif ( function_exists('finfo_file') ) { + $finfo = finfo_open( FILEINFO_MIME ); + $mimeType = finfo_file( $finfo, $file ); + finfo_close($finfo); + return( $mimeType ); + } + return( trim( exec( 'file -bi '.escapeshellarg( $file ).' 2>/dev/null' ) ) ); } function outputVideoStream( $id, $src, $width, $height, $format, $title="" ) { @@ -362,2123 +323,1768 @@ function getImageStream( $id, $src, $width, $height, $title="" ) { } } -function outputControlStream( $src, $width, $height, $monitor, $scale, $target ) -{ +function outputControlStream( $src, $width, $height, $monitor, $scale, $target ) { ?> -
- - - - - - - - - - - - -
+
+ + + + + + + + + + + + +
- - - - + + + + -<?php echo $title ?> + <?php echo $title ?> -
- - - - - - - - - - - - -
+
+ + + + + + + + + + + + +
= 2; $i-- ) { - $deletePath = join( '/', array_slice( $pathParts, 0, $i ) ); - if ( !glob( $deletePath."/*" ) ) { - deletePath( $deletePath ); - } - } - } else { - Warning( "Found no event files under $eventlink_path" ); - } # end if found files - } else { - $eventPath = implode( '/', array( ZM_DIR_EVENTS, $mid, $event['Id'] ) ); - deletePath( $eventPath ); - } # USE_DEEP_STORAGE OR NOT - } # ! ZM_OPT_FAST_DELETE - } # CAN EDIT + if ( $id_files = glob( $eventlink_path ) ) { +# I know we are using arrays here, but really there can only ever be 1 in the array + $eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] ); + deletePath( $eventPath ); + deletePath( $id_files[0] ); + $pathParts = explode( '/', $eventPath ); + for ( $i = count($pathParts)-1; $i >= 2; $i-- ) { + $deletePath = join( '/', array_slice( $pathParts, 0, $i ) ); + if ( !glob( $deletePath."/*" ) ) { + deletePath( $deletePath ); + } + } + } else { + Warning( "Found no event files under $eventlink_path" ); + } # end if found files + } else { + $eventPath = implode( '/', array( ZM_DIR_EVENTS, $mid, $event['Id'] ) ); + deletePath( $eventPath ); + } # USE_DEEP_STORAGE OR NOT + } # ! ZM_OPT_FAST_DELETE + } # CAN EDIT } -function makeLink( $url, $label, $condition=1, $options="" ) -{ - $string = ""; - if ( $condition ) - { - $string .= ''; - } - $string .= $label; - if ( $condition ) - { - $string .= ''; - } - return( $string ); +function makeLink( $url, $label, $condition=1, $options="" ) { + $string = ""; + if ( $condition ) { + $string .= ''; + } + $string .= $label; + if ( $condition ) { + $string .= ''; + } + return( $string ); } -function makePopupLink( $url, $winName, $winSize, $label, $condition=1, $options="" ) -{ - $string = ""; - if ( $condition ) - { - if ( is_array( $winSize ) ) - $popupParms = "'".$url."', '".$winName."', '".$winSize[0]."', ".$winSize[1].", ".$winSize[2]; - else - $popupParms = "'".$url."', '".$winName."', '".$winSize."'"; - - $string .= ''; - } - $string .= $label; - if ( $condition ) - { - $string .= ''; - } - return( $string ); -} - -function makePopupButton( $url, $winName, $winSize, $buttonValue, $condition=1, $options="" ) -{ +function makePopupLink( $url, $winName, $winSize, $label, $condition=1, $options="" ) { + $string = ""; + if ( $condition ) { if ( is_array( $winSize ) ) - $popupParms = "'".$url."', '".$winName."', '".$winSize[0]."', ".$winSize[1].", ".$winSize[2]; + $popupParms = "'".$url."', '".$winName."', '".$winSize[0]."', ".$winSize[1].", ".$winSize[2]; else - $popupParms = "'".$url."', '".$winName."', '".$winSize."'"; - $string = ''; - return( $string ); + $popupParms = "'".$url."', '".$winName."', '".$winSize."'"; + + $string .= ''; + } + $string .= $label; + if ( $condition ) { + $string .= ''; + } + return( $string ); } -function truncText( $text, $length, $deslash=1 ) -{ - return( preg_replace( "/^(.{".$length.",}?)\b.*$/", "\\1…", ($deslash?stripslashes($text):$text) ) ); +function makePopupButton( $url, $winName, $winSize, $buttonValue, $condition=1, $options="" ) { + if ( is_array( $winSize ) ) + $popupParms = "'".$url."', '".$winName."', '".$winSize[0]."', ".$winSize[1].", ".$winSize[2]; + else + $popupParms = "'".$url."', '".$winName."', '".$winSize."'"; + $string = ''; + return( $string ); +} + +function truncText( $text, $length, $deslash=1 ) { + return( preg_replace( "/^(.{".$length.",}?)\b.*$/", "\\1…", ($deslash?stripslashes($text):$text) ) ); } -function buildSelect( $name, $contents, $behaviours=false ) -{ - $value = ""; - if ( preg_match( "/^\s*(\w+)\s*(\[.*\])?\s*$/", $name, $matches ) && count($matches) > 2 ) - { - $arr = $matches[1]; - if ( isset($GLOBALS[$arr]) ) - $value = $GLOBALS[$arr]; - elseif ( isset($_REQUEST[$arr]) ) - $value = $_REQUEST[$arr]; - if ( !preg_match_all( "/\[\s*['\"]?(\w+)[\"']?\s*\]/", $matches[2], $matches ) ) +function buildSelect( $name, $contents, $behaviours=false ) { + $value = ""; + if ( preg_match( "/^\s*(\w+)\s*(\[.*\])?\s*$/", $name, $matches ) && count($matches) > 2 ) { + $arr = $matches[1]; + if ( isset($GLOBALS[$arr]) ) + $value = $GLOBALS[$arr]; + elseif ( isset($_REQUEST[$arr]) ) + $value = $_REQUEST[$arr]; + if ( !preg_match_all( "/\[\s*['\"]?(\w+)[\"']?\s*\]/", $matches[2], $matches ) ) { + Fatal( "Can't parse selector '$name'" ); + } + for ( $i = 0; $i < count($matches[1]); $i++ ) { + $idx = $matches[1][$i]; + $value = isset($value[$idx])?$value[$idx]:false; + } + } else { + if ( isset($GLOBALS[$name]) ) + $value = $GLOBALS[$name]; + elseif ( isset($_REQUEST[$name]) ) + $value = $_REQUEST[$name]; + } + ob_start(); + $behaviourText = ""; + if ( !empty($behaviours) ) { + if ( is_array($behaviours) ) { + foreach ( $behaviours as $event=>$action ) { + $behaviourText .= ' '.$event.'="'.$action.'"'; + } + } else { + $behaviourText = ' onchange="'.$behaviours.'"'; + } + } + ?> + + $value ) { + if ( $columns && !$columns[$key] ) + continue; + + if ( !isset($types[$key]) ) + $types[$key] = false; + switch( $types[$key] ) { + case 'set' : { - Fatal( "Can't parse selector '$name'" ); + if ( is_array( $newValues[$key] ) ) { + if ( join(',',$newValues[$key]) != $values[$key] ) { + $changes[$key] = "$key = ".dbEscape(join(',',$newValues[$key])); + } + } elseif ( $values[$key] ) { + $changes[$key] = "$key = ''"; + } + break; } - for ( $i = 0; $i < count($matches[1]); $i++ ) + case 'image' : { - $idx = $matches[1][$i]; - $value = isset($value[$idx])?$value[$idx]:false; + if ( is_array( $newValues[$key] ) ) { + $imageData = getimagesize( $newValues[$key]['tmp_name'] ); + $changes[$key.'Width'] = $key."Width = ".$imageData[0]; + $changes[$key.'Height'] = $key."Height = ".$imageData[1]; + $changes[$key.'Type'] = $key."Type = '".$newValues[$key]['type']."'"; + $changes[$key.'Size'] = $key."Size = ".$newValues[$key]['size']; + ob_start(); + readfile( $newValues[$key]['tmp_name'] ); + $changes[$key] = $key." = ".dbEscape( ob_get_contents() ); + ob_end_clean(); + } else { + $changes[$key] = "$key = ".dbEscape($value); + } + break; + } + case 'document' : + { + if ( is_array( $newValues[$key] ) ) { + $imageData = getimagesize( $newValues[$key]['tmp_name'] ); + $changes[$key.'Type'] = $key."Type = '".$newValues[$key]['type']."'"; + $changes[$key.'Size'] = $key."Size = ".$newValues[$key]['size']; + ob_start(); + readfile( $newValues[$key]['tmp_name'] ); + $changes[$key] = $key." = ".dbEscape( ob_get_contents() ); + ob_end_clean(); + } else { + $changes[$key] = "$key = ".dbEscape($value); + } + break; + } + case 'file' : + { + $changes[$key.'Type'] = $key."Type = ".dbEscape($newValues[$key]['type']); + $changes[$key.'Size'] = $key."Size = ".dbEscape($newValues[$key]['size']); + ob_start(); + readfile( $newValues[$key]['tmp_name'] ); + $changes[$key] = $key." = '".dbEscape( ob_get_contents() )."'"; + ob_end_clean(); + break; + } + case 'raw' : + { + if ( $values[$key] != $value ) { + $changes[$key] = "$key = ".dbEscape($value); + } + break; + } + default : + { + if ( !isset($values[$key]) || ($values[$key] != $value) ) { + $changes[$key] = "$key = ".dbEscape(trim($value)); + } + break; } } - else - { - if ( isset($GLOBALS[$name]) ) - $value = $GLOBALS[$name]; - elseif ( isset($_REQUEST[$name]) ) - $value = $_REQUEST[$name]; + } + foreach( $values as $key=>$value ) { + if ( !empty($columns[$key]) ) { + if ( !empty($types[$key]) ) { + if ( $types[$key] == 'toggle' ) { + if ( !isset($newValues[$key]) && !empty($value) ) { + $changes[$key] = "$key = 0"; + } + } else if ( $types[$key] == 'set' ) { + $changes[$key] = "$key = ''"; + } + } } - ob_start(); - $behaviourText = ""; - if ( !empty($behaviours) ) - { - if ( is_array($behaviours) ) - { - foreach ( $behaviours as $event=>$action ) - { - $behaviourText .= ' '.$event.'="'.$action.'"'; - } - } - else - { - $behaviourText = ' onchange="'.$behaviours.'"'; - } + } + return( $changes ); +} + +function getBrowser( &$browser, &$version ) { + if ( isset($_SESSION['browser']) ) { + $browser = $_SESSION['browser']; + $version = $_SESSION['version']; + } else { + if (( preg_match( '/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $logVersion)) || (preg_match( '/.*Trident.*rv:(.*?)(;|\))/', $_SERVER['HTTP_USER_AGENT'], $logVersion))) { + $version = $logVersion[1]; + $browser = 'ie'; + } elseif ( preg_match( '/Chrome\/([0-9.]+)/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) { + $version = $logVersion[1]; + // Check for old version of Chrome with bug 5876 + if ( $version < 7 ) { + $browser = 'oldchrome'; + } else { + $browser = 'chrome'; + } + } elseif ( preg_match( '/Safari\/([0-9.]+)/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) { + $version = $logVersion[1]; + $browser = 'safari'; + } elseif ( preg_match( '/Opera[ \/]([0-9].[0-9]{1,2})/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) { + $version = $logVersion[1]; + $browser = 'opera'; + } elseif ( preg_match( '/Konqueror\/([0-9.]+)/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) { + $version = $logVersion[1]; + $browser = 'konqueror'; + } elseif ( preg_match( '/Mozilla\/([0-9].[0-9]{1,2})/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) { + $version = $logVersion[1]; + $browser = 'mozilla'; + } else { + $version = 0; + $browser = 'unknown'; } -?> - -/dev/null >&- <&- >/dev/null"; + exec( $string ); } -function getFormChanges( $values, $newValues, $types=false, $columns=false ) -{ - $changes = array(); - if ( !$types ) - $types = array(); - - foreach( $newValues as $key=>$value ) - { - if ( $columns && !$columns[$key] ) - continue; - - if ( !isset($types[$key]) ) - $types[$key] = false; - switch( $types[$key] ) - { - case 'set' : - { - if ( is_array( $newValues[$key] ) ) - { - if ( join(',',$newValues[$key]) != $values[$key] ) - { - $changes[$key] = "$key = ".dbEscape(join(',',$newValues[$key])); - } - } - elseif ( $values[$key] ) - { - $changes[$key] = "$key = ''"; - } - break; - } - case 'image' : - { - if ( is_array( $newValues[$key] ) ) - { - $imageData = getimagesize( $newValues[$key]['tmp_name'] ); - $changes[$key.'Width'] = $key."Width = ".$imageData[0]; - $changes[$key.'Height'] = $key."Height = ".$imageData[1]; - $changes[$key.'Type'] = $key."Type = '".$newValues[$key]['type']."'"; - $changes[$key.'Size'] = $key."Size = ".$newValues[$key]['size']; - ob_start(); - readfile( $newValues[$key]['tmp_name'] ); - $changes[$key] = $key." = ".dbEscape( ob_get_contents() ); - ob_end_clean(); - } - else - { - $changes[$key] = "$key = ".dbEscape($value); - } - break; - } - case 'document' : - { - if ( is_array( $newValues[$key] ) ) - { - $imageData = getimagesize( $newValues[$key]['tmp_name'] ); - $changes[$key.'Type'] = $key."Type = '".$newValues[$key]['type']."'"; - $changes[$key.'Size'] = $key."Size = ".$newValues[$key]['size']; - ob_start(); - readfile( $newValues[$key]['tmp_name'] ); - $changes[$key] = $key." = ".dbEscape( ob_get_contents() ); - ob_end_clean(); - } - else - { - $changes[$key] = "$key = ".dbEscape($value); - } - break; - } - case 'file' : - { - $changes[$key.'Type'] = $key."Type = ".dbEscape($newValues[$key]['type']); - $changes[$key.'Size'] = $key."Size = ".dbEscape($newValues[$key]['size']); - ob_start(); - readfile( $newValues[$key]['tmp_name'] ); - $changes[$key] = $key." = '".dbEscape( ob_get_contents() )."'"; - ob_end_clean(); - break; - } - case 'raw' : - { - if ( $values[$key] != $value ) - { - $changes[$key] = "$key = ".dbEscape($value); - } - break; - } - default : - { - if ( !isset($values[$key]) || ($values[$key] != $value) ) - { - $changes[$key] = "$key = ".dbEscape(trim($value)); - } - break; - } - } - } - foreach( $values as $key=>$value ) - { - if ( !empty($columns[$key]) ) - { - if ( !empty($types[$key]) ) - { - if ( $types[$key] == 'toggle' ) - { - if ( !isset($newValues[$key]) && !empty($value) ) - { - $changes[$key] = "$key = 0"; - } - } - else if ( $types[$key] == 'set' ) - { - $changes[$key] = "$key = ''"; - } - } - } - } - return( $changes ); -} - -function getBrowser( &$browser, &$version ) -{ - if ( isset($_SESSION['browser']) ) - { - $browser = $_SESSION['browser']; - $version = $_SESSION['version']; - } - else - { - if (( preg_match( '/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $logVersion)) || (preg_match( '/.*Trident.*rv:(.*?)(;|\))/', $_SERVER['HTTP_USER_AGENT'], $logVersion))) - { - $version = $logVersion[1]; - $browser = 'ie'; - } - elseif ( preg_match( '/Chrome\/([0-9.]+)/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) - { - $version = $logVersion[1]; - // Check for old version of Chrome with bug 5876 - if ( $version < 7 ) - { - $browser = 'oldchrome'; - } - else - { - $browser = 'chrome'; - } - } - elseif ( preg_match( '/Safari\/([0-9.]+)/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) - { - $version = $logVersion[1]; - $browser = 'safari'; - } - elseif ( preg_match( '/Opera[ \/]([0-9].[0-9]{1,2})/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) - { - $version = $logVersion[1]; - $browser = 'opera'; - } - elseif ( preg_match( '/Konqueror\/([0-9.]+)/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) - { - $version = $logVersion[1]; - $browser = 'konqueror'; - } - elseif ( preg_match( '/Mozilla\/([0-9].[0-9]{1,2})/', $_SERVER['HTTP_USER_AGENT'], $logVersion) ) - { - $version = $logVersion[1]; - $browser = 'mozilla'; - } - else - { - $version = 0; - $browser = 'unknown'; - } - $_SESSION['browser'] = $browser; - $_SESSION['version'] = $version; - } -} - -function isMozilla() -{ - getBrowser( $browser, $version ); - - return( $browser == "mozilla" ); -} - -function isKonqueror() -{ - getBrowser( $browser, $version ); - - return( $browser == "konqueror" ); -} - -function isInternetExplorer() -{ - getBrowser( $browser, $version ); - - return( $browser == "ie" ); -} - -function isOldChrome() -{ - getBrowser( $browser, $version ); - - return( $browser == "oldchrome" ); -} - -function isChrome() -{ - getBrowser( $browser, $version ); - - return( $browser == "chrome" ); -} - -function isOpera() -{ - getBrowser( $browser, $version ); - - return( $browser == "opera" ); -} - -function isSafari() -{ - getBrowser( $browser, $version ); - - return( $browser == "safari" ); -} - -function isWindows() -{ - return ( preg_match( '/Win/', $_SERVER['HTTP_USER_AGENT'] ) ); -} - -function canStreamIframe() -{ - return( isKonqueror() ); -} - -function canStreamNative() -{ - // Old versions of Chrome can display the stream, but then it blocks everything else (Chrome bug 5876) - return( ZM_WEB_CAN_STREAM == "yes" || ( ZM_WEB_CAN_STREAM == "auto" && (!isInternetExplorer() && !isOldChrome()) ) ); -} - -function canStreamApplet() -{ - if ( (ZM_OPT_CAMBOZOLA && !file_exists( ZM_PATH_WEB.'/'.ZM_PATH_CAMBOZOLA )) ) - { - Warning ( "ZM_OPT_CAMBOZOLA is enabled, but the system cannot find ".ZM_PATH_WEB."/".ZM_PATH_CAMBOZOLA ); - } - - return( (ZM_OPT_CAMBOZOLA && file_exists( ZM_PATH_WEB.'/'.ZM_PATH_CAMBOZOLA )) ); -} - -function canStream() -{ - return( canStreamNative() | canStreamApplet() ); -} - -function packageControl( $command ) -{ - $string = ZM_PATH_BIN.'/zmpkg.pl '.escapeshellarg( $command ); - $string .= " 2>/dev/null >&- <&- >/dev/null"; - exec( $string ); -} - -function daemonControl( $command, $daemon=false, $args=false ) -{ - $string = ZM_PATH_BIN."/zmdc.pl $command"; - if ( $daemon ) - { - $string .= " $daemon"; - if ( $args ) - { - $string .= " $args"; - } - } - $string .= " 2>/dev/null >&- <&- >/dev/null"; - exec( $string ); -} - -function zmcControl( $monitor, $mode=false ) -{ +function zmcControl( $monitor, $mode=false ) { if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$monitor['ServerId'] ) ) { - $row = NULL; - if ( $monitor['Type'] == "Local" ) - { - $row = dbFetchOne( "select count(if(Function!='None',1,NULL)) as ActiveCount from Monitors where Device = ?", NULL, array($monitor['Device']) ); - $zmcArgs = "-d ".$monitor['Device']; - } - else - { - $row = dbFetchOne( "select count(if(Function!='None',1,NULL)) as ActiveCount from Monitors where Id = ?", NULL, array($monitor['Id']) ); - $zmcArgs = "-m ".$monitor['Id']; + $row = NULL; + if ( $monitor['Type'] == "Local" ) { + $row = dbFetchOne( "select count(if(Function!='None',1,NULL)) as ActiveCount from Monitors where Device = ?", NULL, array($monitor['Device']) ); + $zmcArgs = "-d ".$monitor['Device']; + } else { + $row = dbFetchOne( "select count(if(Function!='None',1,NULL)) as ActiveCount from Monitors where Id = ?", NULL, array($monitor['Id']) ); + $zmcArgs = "-m ".$monitor['Id']; } $activeCount = $row['ActiveCount']; - if ( !$activeCount || $mode == "stop" ) - { + if ( !$activeCount || $mode == "stop" ) { + daemonControl( "stop", "zmc", $zmcArgs ); + } else { + if ( $mode == "restart" ) { daemonControl( "stop", "zmc", $zmcArgs ); - } - else - { - if ( $mode == "restart" ) - { - daemonControl( "stop", "zmc", $zmcArgs ); - } - daemonControl( "start", "zmc", $zmcArgs ); + } + daemonControl( "start", "zmc", $zmcArgs ); } } } -function zmaControl( $monitor, $mode=false ) -{ +function zmaControl( $monitor, $mode=false ) { if ( (!defined('ZM_SERVER_ID')) or ( ZM_SERVER_ID==$monitor['ServerId'] ) ) { - if ( !is_array( $monitor ) ) - { - $monitor = dbFetchOne( "select C.*, M.* from Monitors as M left join Controls as C on (M.ControlId = C.Id ) where M.Id=?", NULL, array($monitor) ); + if ( !is_array( $monitor ) ) { + $monitor = dbFetchOne( "select C.*, M.* from Monitors as M left join Controls as C on (M.ControlId = C.Id ) where M.Id=?", NULL, array($monitor) ); } - if ( !$monitor || $monitor['Function'] == 'None' || $monitor['Function'] == 'Monitor' || $mode == "stop" ) - { - if ( ZM_OPT_CONTROL ) - { - daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] ); + if ( !$monitor || $monitor['Function'] == 'None' || $monitor['Function'] == 'Monitor' || $mode == "stop" ) { + if ( ZM_OPT_CONTROL ) { + daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] ); + } + daemonControl( "stop", "zma", "-m ".$monitor['Id'] ); + if ( ZM_OPT_FRAME_SERVER ) { + daemonControl( "stop", "zmf", "-m ".$monitor['Id'] ); + } + } else { + if ( $mode == "restart" ) { + if ( ZM_OPT_CONTROL ) { + daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] ); } daemonControl( "stop", "zma", "-m ".$monitor['Id'] ); - if ( ZM_OPT_FRAME_SERVER ) - { - daemonControl( "stop", "zmf", "-m ".$monitor['Id'] ); - } - } - else - { - if ( $mode == "restart" ) - { - if ( ZM_OPT_CONTROL ) - { - daemonControl( "stop", "zmtrack.pl", "-m ".$monitor['Id'] ); - } - daemonControl( "stop", "zma", "-m ".$monitor['Id'] ); - if ( ZM_OPT_FRAME_SERVER ) - { - daemonControl( "stop", "zmf", "-m ".$monitor['Id'] ); - } - } - if ( ZM_OPT_FRAME_SERVER ) - { - daemonControl( "start", "zmf", "-m ".$monitor['Id'] ); - } - daemonControl( "start", "zma", "-m ".$monitor['Id'] ); - if ( ZM_OPT_CONTROL && $monitor['Controllable'] && $monitor['TrackMotion'] && ( $monitor['Function'] == 'Modect' || $monitor['Function'] == 'Mocord' ) ) - { - daemonControl( "start", "zmtrack.pl", "-m ".$monitor['Id'] ); - } - if ( $mode == "reload" ) - { - daemonControl( "reload", "zma", "-m ".$monitor['Id'] ); + if ( ZM_OPT_FRAME_SERVER ) { + daemonControl( "stop", "zmf", "-m ".$monitor['Id'] ); } + } + if ( ZM_OPT_FRAME_SERVER ) { + daemonControl( "start", "zmf", "-m ".$monitor['Id'] ); + } + daemonControl( "start", "zma", "-m ".$monitor['Id'] ); + if ( ZM_OPT_CONTROL && $monitor['Controllable'] && $monitor['TrackMotion'] && ( $monitor['Function'] == 'Modect' || $monitor['Function'] == 'Mocord' ) ) { + daemonControl( "start", "zmtrack.pl", "-m ".$monitor['Id'] ); + } + if ( $mode == "reload" ) { + daemonControl( "reload", "zma", "-m ".$monitor['Id'] ); + } } } } -function initDaemonStatus() -{ - global $daemon_status; +function initDaemonStatus() { + global $daemon_status; - if ( !isset($daemon_status) ) - { - if ( daemonCheck() ) - { - $string = ZM_PATH_BIN."/zmdc.pl status"; - $daemon_status = shell_exec( $string ); - } - else - { - $daemon_status = ""; - } + if ( !isset($daemon_status) ) { + if ( daemonCheck() ) { + $string = ZM_PATH_BIN."/zmdc.pl status"; + $daemon_status = shell_exec( $string ); + } else { + $daemon_status = ""; } + } } -function daemonStatus( $daemon, $args=false ) -{ - global $daemon_status; +function daemonStatus( $daemon, $args=false ) { + global $daemon_status; - initDaemonStatus(); - - $string = "$daemon"; + initDaemonStatus(); + + $string = "$daemon"; + if ( $args ) + $string .= " $args"; + return( strpos( $daemon_status, "'$string' running" ) !== false ); +} + +function zmcStatus( $monitor ) { + if ( $monitor['Type'] == 'Local' ) { + $zmcArgs = "-d ".$monitor['Device']; + } else { + $zmcArgs = "-m ".$monitor['Id']; + } + return( daemonStatus( "zmc", $zmcArgs ) ); +} + +function zmaStatus( $monitor ) { + if ( is_array( $monitor ) ) { + $monitor = $monitor['Id']; + } + return( daemonStatus( "zma", "-m $monitor" ) ); +} + +function daemonCheck( $daemon=false, $args=false ) { + $string = ZM_PATH_BIN."/zmdc.pl check"; + if ( $daemon ) { + $string .= " $daemon"; if ( $args ) - $string .= " $args"; - return( strpos( $daemon_status, "'$string' running" ) !== false ); + $string .= " $args"; + } + $result = exec( $string ); + return( preg_match( '/running/', $result ) ); } -function zmcStatus( $monitor ) -{ - if ( $monitor['Type'] == 'Local' ) - { - $zmcArgs = "-d ".$monitor['Device']; - } +function zmcCheck( $monitor ) { + if ( $monitor['Type'] == 'Local' ) { + $zmcArgs = "-d ".$monitor['Device']; + } else { + $zmcArgs = "-m ".$monitor['Id']; + } + return( daemonCheck( "zmc", $zmcArgs ) ); +} + +function zmaCheck( $monitor ) { + if ( is_array( $monitor ) ) { + $monitor = $monitor['Id']; + } + return( daemonCheck( "zma", "-m $monitor" ) ); +} + +function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) { + $eventPath = getEventPath( $event ); + + if ( !is_array($frame) ) + $frame = array( 'FrameId'=>$frame, 'Type'=>'' ); + + //echo "S:$scale, CO:$captureOnly
"; + $captImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $frame['FrameId'] ); + $captPath = $eventPath.'/'.$captImage; + $thumbCaptPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$captImage; + //echo "CI:$captImage, CP:$captPath, TCP:$thumbCaptPath
"; + + $analImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-analyse.jpg", $frame['FrameId'] ); + $analPath = $eventPath.'/'.$analImage; + $analFile = ZM_DIR_EVENTS."/".$analPath; + $thumbAnalPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$analImage; + //echo "AI:$analImage, AP:$analPath, TAP:$thumbAnalPath
"; + + $alarmFrame = $frame['Type']=='Alarm'; + + $hasAnalImage = $alarmFrame && file_exists( $analFile ) && filesize( $analFile ); + $isAnalImage = $hasAnalImage && !$captureOnly; + + if ( !ZM_WEB_SCALE_THUMBS || $scale >= SCALE_BASE || !function_exists( 'imagecreatefromjpeg' ) ) { + $imagePath = $thumbPath = $isAnalImage?$analPath:$captPath; + $imageFile = ZM_DIR_EVENTS."/".$imagePath; + $thumbFile = ZM_DIR_EVENTS."/".$thumbPath; + } else { + if ( version_compare( phpversion(), "4.3.10", ">=") ) + $fraction = sprintf( "%.3F", $scale/SCALE_BASE ); else - { - $zmcArgs = "-m ".$monitor['Id']; + $fraction = sprintf( "%.3f", $scale/SCALE_BASE ); + $scale = (int)round( $scale ); + + $thumbCaptPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $thumbCaptPath ); + $thumbAnalPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $thumbAnalPath ); + + if ( $isAnalImage ) { + $imagePath = $analPath; + $thumbPath = $thumbAnalPath; + } else { + $imagePath = $captPath; + $thumbPath = $thumbCaptPath; } - return( daemonStatus( "zmc", $zmcArgs ) ); + + $imageFile = ZM_DIR_EVENTS."/".$imagePath; + //$thumbFile = ZM_DIR_EVENTS."/".$thumbPath; + $thumbFile = $thumbPath; + if ( $overwrite || !file_exists( $thumbFile ) || !filesize( $thumbFile ) ) { + // Get new dimensions + list( $imageWidth, $imageHeight ) = getimagesize( $imageFile ); + $thumbWidth = $imageWidth * $fraction; + $thumbHeight = $imageHeight * $fraction; + + // Resample + $thumbImage = imagecreatetruecolor( $thumbWidth, $thumbHeight ); + $image = imagecreatefromjpeg( $imageFile ); + imagecopyresampled( $thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight ); + + if ( !imagejpeg( $thumbImage, $thumbFile ) ) + Error( "Can't create thumbnail '$thumbPath'" ); + } + } + + $imageData = array( + 'eventPath' => $eventPath, + 'imagePath' => $imagePath, + 'thumbPath' => $thumbPath, + 'imageFile' => $imageFile, + 'thumbFile' => $thumbFile, + 'imageClass' => $alarmFrame?"alarm":"normal", + 'isAnalImage' => $isAnalImage, + 'hasAnalImage' => $hasAnalImage, + ); + + //echo "IP:$imagePath
"; + //echo "TP:$thumbPath
"; + return( $imageData ); } -function zmaStatus( $monitor ) -{ - if ( is_array( $monitor ) ) - { - $monitor = $monitor['Id']; - } - return( daemonStatus( "zma", "-m $monitor" ) ); +function viewImagePath( $path, $querySep='&' ) { + if ( strncmp( $path, ZM_DIR_IMAGES, strlen(ZM_DIR_IMAGES) ) == 0 ) { + // Thumbnails + return( $path ); + } elseif ( strpos( ZM_DIR_EVENTS, '/' ) === 0 ) { + return( '?view=image'.$querySep.'path='.$path ); + } + return( ZM_DIR_EVENTS.'/'.$path ); } -function daemonCheck( $daemon=false, $args=false ) -{ - $string = ZM_PATH_BIN."/zmdc.pl check"; - if ( $daemon ) - { - $string .= " $daemon"; - if ( $args ) - $string .= " $args"; - } - $result = exec( $string ); - return( preg_match( '/running/', $result ) ); +function createListThumbnail( $event, $overwrite=false ) { + if ( !($frame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND Score=? ORDER BY FrameId LIMIT 1", NULL, array( $event['Id'], $event['MaxScore'] ) )) ) + return( false ); + + $frameId = $frame['FrameId']; + + if ( ZM_WEB_LIST_THUMB_WIDTH ) { + $thumbWidth = ZM_WEB_LIST_THUMB_WIDTH; + $scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$event['Width']; + $thumbHeight = reScale( $event['Height'], $scale ); + } elseif ( ZM_WEB_LIST_THUMB_HEIGHT ) { + $thumbHeight = ZM_WEB_LIST_THUMB_HEIGHT; + $scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_HEIGHT)/$event['Height']; + $thumbWidth = reScale( $event['Width'], $scale ); + } else { + Fatal( "No thumbnail width or height specified, please check in Options->Web" ); + } + + $imageData = getImageSrc( $event, $frame, $scale, false, $overwrite ); + $thumbData = $frame; + $thumbData['Path'] = $imageData['thumbPath']; + $thumbData['Width'] = (int)$thumbWidth; + $thumbData['Height'] = (int)$thumbHeight; + + return( $thumbData ); } -function zmcCheck( $monitor ) -{ - if ( $monitor['Type'] == 'Local' ) - { - $zmcArgs = "-d ".$monitor['Device']; - } +function createVideo( $event, $format, $rate, $scale, $overwrite=false ) { + $command = ZM_PATH_BIN."/zmvideo.pl -e ".$event['Id']." -f ".$format." -r ".sprintf( "%.2F", ($rate/RATE_BASE) ); + if ( preg_match( '/\d+x\d+/', $scale ) ) + $command .= " -S ".$scale; + else + if ( version_compare( phpversion(), "4.3.10", ">=") ) + $command .= " -s ".sprintf( "%.2F", ($scale/SCALE_BASE) ); else - { - $zmcArgs = "-m ".$monitor['Id']; - } - return( daemonCheck( "zmc", $zmcArgs ) ); + $command .= " -s ".sprintf( "%.2f", ($scale/SCALE_BASE) ); + if ( $overwrite ) + $command .= " -o"; + $result = exec( escapeshellcmd( $command ), $output, $status ); + return( $status?"":rtrim($result) ); } -function zmaCheck( $monitor ) -{ - if ( is_array( $monitor ) ) - { - $monitor = $monitor['Id']; - } - return( daemonCheck( "zma", "-m $monitor" ) ); -} - -function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) -{ - $eventPath = getEventPath( $event ); - - if ( !is_array($frame) ) - $frame = array( 'FrameId'=>$frame, 'Type'=>'' ); - - //echo "S:$scale, CO:$captureOnly
"; - $captImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $frame['FrameId'] ); - $captPath = $eventPath.'/'.$captImage; - $thumbCaptPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$captImage; - //echo "CI:$captImage, CP:$captPath, TCP:$thumbCaptPath
"; - - $analImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-analyse.jpg", $frame['FrameId'] ); - $analPath = $eventPath.'/'.$analImage; - $analFile = ZM_DIR_EVENTS."/".$analPath; - $thumbAnalPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$analImage; - //echo "AI:$analImage, AP:$analPath, TAP:$thumbAnalPath
"; - - $alarmFrame = $frame['Type']=='Alarm'; - - $hasAnalImage = $alarmFrame && file_exists( $analFile ) && filesize( $analFile ); - $isAnalImage = $hasAnalImage && !$captureOnly; - - if ( !ZM_WEB_SCALE_THUMBS || $scale >= SCALE_BASE || !function_exists( 'imagecreatefromjpeg' ) ) - { - $imagePath = $thumbPath = $isAnalImage?$analPath:$captPath; - $imageFile = ZM_DIR_EVENTS."/".$imagePath; - $thumbFile = ZM_DIR_EVENTS."/".$thumbPath; - } - else - { - if ( version_compare( phpversion(), "4.3.10", ">=") ) - $fraction = sprintf( "%.3F", $scale/SCALE_BASE ); - else - $fraction = sprintf( "%.3f", $scale/SCALE_BASE ); - $scale = (int)round( $scale ); - - $thumbCaptPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $thumbCaptPath ); - $thumbAnalPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $thumbAnalPath ); - - if ( $isAnalImage ) - { - $imagePath = $analPath; - $thumbPath = $thumbAnalPath; - } - else - { - $imagePath = $captPath; - $thumbPath = $thumbCaptPath; - } - - $imageFile = ZM_DIR_EVENTS."/".$imagePath; - //$thumbFile = ZM_DIR_EVENTS."/".$thumbPath; - $thumbFile = $thumbPath; - if ( $overwrite || !file_exists( $thumbFile ) || !filesize( $thumbFile ) ) - { - // Get new dimensions - list( $imageWidth, $imageHeight ) = getimagesize( $imageFile ); - $thumbWidth = $imageWidth * $fraction; - $thumbHeight = $imageHeight * $fraction; - - // Resample - $thumbImage = imagecreatetruecolor( $thumbWidth, $thumbHeight ); - $image = imagecreatefromjpeg( $imageFile ); - imagecopyresampled( $thumbImage, $image, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imageWidth, $imageHeight ); - - if ( !imagejpeg( $thumbImage, $thumbFile ) ) - Error( "Can't create thumbnail '$thumbPath'" ); - } - } - - $imageData = array( - 'eventPath' => $eventPath, - 'imagePath' => $imagePath, - 'thumbPath' => $thumbPath, - 'imageFile' => $imageFile, - 'thumbFile' => $thumbFile, - 'imageClass' => $alarmFrame?"alarm":"normal", - 'isAnalImage' => $isAnalImage, - 'hasAnalImage' => $hasAnalImage, - ); - - //echo "IP:$imagePath
"; - //echo "TP:$thumbPath
"; - return( $imageData ); -} - -function viewImagePath( $path, $querySep='&' ) -{ - if ( strncmp( $path, ZM_DIR_IMAGES, strlen(ZM_DIR_IMAGES) ) == 0 ) - { - // Thumbnails - return( $path ); - } - elseif ( strpos( ZM_DIR_EVENTS, '/' ) === 0 ) - { - return( '?view=image'.$querySep.'path='.$path ); - } - return( ZM_DIR_EVENTS.'/'.$path ); -} - -function createListThumbnail( $event, $overwrite=false ) -{ - if ( !($frame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND Score=? ORDER BY FrameId LIMIT 1", NULL, array( $event['Id'], $event['MaxScore'] ) )) ) - return( false ); - - $frameId = $frame['FrameId']; - - if ( ZM_WEB_LIST_THUMB_WIDTH ) - { - $thumbWidth = ZM_WEB_LIST_THUMB_WIDTH; - $scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_WIDTH)/$event['Width']; - $thumbHeight = reScale( $event['Height'], $scale ); - } - elseif ( ZM_WEB_LIST_THUMB_HEIGHT ) - { - $thumbHeight = ZM_WEB_LIST_THUMB_HEIGHT; - $scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_HEIGHT)/$event['Height']; - $thumbWidth = reScale( $event['Width'], $scale ); - } - else - { - Fatal( "No thumbnail width or height specified, please check in Options->Web" ); - } - - $imageData = getImageSrc( $event, $frame, $scale, false, $overwrite ); - $thumbData = $frame; - $thumbData['Path'] = $imageData['thumbPath']; - $thumbData['Width'] = (int)$thumbWidth; - $thumbData['Height'] = (int)$thumbHeight; - - return( $thumbData ); -} - -function createVideo( $event, $format, $rate, $scale, $overwrite=false ) -{ - $command = ZM_PATH_BIN."/zmvideo.pl -e ".$event['Id']." -f ".$format." -r ".sprintf( "%.2F", ($rate/RATE_BASE) ); - if ( preg_match( '/\d+x\d+/', $scale ) ) - $command .= " -S ".$scale; - else - if ( version_compare( phpversion(), "4.3.10", ">=") ) - $command .= " -s ".sprintf( "%.2F", ($scale/SCALE_BASE) ); - else - $command .= " -s ".sprintf( "%.2f", ($scale/SCALE_BASE) ); - if ( $overwrite ) - $command .= " -o"; - $result = exec( escapeshellcmd( $command ), $output, $status ); - return( $status?"":rtrim($result) ); -} - -function executeFilter( $filter ) -{ - $command = ZM_PATH_BIN."/zmfilter.pl --filter ".escapeshellarg($filter); - $result = exec( $command, $output, $status ); - dbQuery( "delete from Filters where Name like '_TempFilter%'" ); - return( $status ); +function executeFilter( $filter ) { + $command = ZM_PATH_BIN."/zmfilter.pl --filter ".escapeshellarg($filter); + $result = exec( $command, $output, $status ); + dbQuery( "delete from Filters where Name like '_TempFilter%'" ); + return( $status ); } # This takes more than one scale amount, so it runs through each and alters dimension. # I can't imagine why you would want to do that. -function reScale( $dimension, $dummy ) -{ - $new_dimension = $dimension; - for ( $i = 1; $i < func_num_args(); $i++ ) - { - $scale = func_get_arg( $i ); - if ( !empty($scale) && $scale != SCALE_BASE ) - $new_dimension = (int)(($new_dimension*$scale)/SCALE_BASE); - } - return( $new_dimension ); +function reScale( $dimension, $dummy ) { + $new_dimension = $dimension; + for ( $i = 1; $i < func_num_args(); $i++ ) { + $scale = func_get_arg( $i ); + if ( !empty($scale) && $scale != SCALE_BASE ) + $new_dimension = (int)(($new_dimension*$scale)/SCALE_BASE); + } + return( $new_dimension ); } -function deScale( $dimension, $dummy ) -{ - $new_dimension = $dimension; - for ( $i = 1; $i < func_num_args(); $i++ ) - { - $scale = func_get_arg( $i ); - if ( !empty($scale) && $scale != SCALE_BASE ) - $new_dimension = (int)(($new_dimension*SCALE_BASE)/$scale); - } - return( $new_dimension ); +function deScale( $dimension, $dummy ) { + $new_dimension = $dimension; + for ( $i = 1; $i < func_num_args(); $i++ ) { + $scale = func_get_arg( $i ); + if ( !empty($scale) && $scale != SCALE_BASE ) + $new_dimension = (int)(($new_dimension*SCALE_BASE)/$scale); + } + return( $new_dimension ); } -function monitorLimitSql() -{ - global $user; - if ( !empty($user['MonitorIds']) ) - $midSql = " and MonitorId in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")"; +function monitorLimitSql() { + global $user; + if ( !empty($user['MonitorIds']) ) + $midSql = " and MonitorId in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")"; + else + $midSql = ''; + return( $midSql ); +} + +function parseSort( $saveToSession=false, $querySep='&' ) { + global $sortQuery, $sortColumn, $sortOrder; // Outputs + + if ( empty($_REQUEST['sort_field']) ) { + $_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD; + $_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc"); + } + switch( $_REQUEST['sort_field'] ) { + case 'Id' : + $sortColumn = "E.Id"; + break; + case 'MonitorName' : + $sortColumn = "M.Name"; + break; + case 'Name' : + $sortColumn = "E.Name"; + break; + case 'Cause' : + $sortColumn = "E.Cause"; + break; + case 'DateTime' : + $_REQUEST['sort_field'] = 'StartTime'; + case 'StartTime' : + $sortColumn = "E.StartTime"; + break; + case 'Length' : + $sortColumn = "E.Length"; + break; + case 'Frames' : + $sortColumn = "E.Frames"; + break; + case 'AlarmFrames' : + $sortColumn = "E.AlarmFrames"; + break; + case 'TotScore' : + $sortColumn = "E.TotScore"; + break; + case 'AvgScore' : + $sortColumn = "E.AvgScore"; + break; + case 'MaxScore' : + $sortColumn = "E.MaxScore"; + break; + default: + $sortColumn = "E.StartTime"; + break; + } + $sortOrder = $_REQUEST['sort_asc']?"asc":"desc"; + if ( !$_REQUEST['sort_asc'] ) + $_REQUEST['sort_asc'] = 0; + $sortQuery = $querySep."sort_field=".validHtmlStr($_REQUEST['sort_field']).$querySep."sort_asc=".validHtmlStr($_REQUEST['sort_asc']); + if ( !isset($_REQUEST['limit']) ) + $_REQUEST['limit'] = ""; + if ( $saveToSession ) { + $_SESSION['sort_field'] = validHtmlStr($_REQUEST['sort_field']); + $_SESSION['sort_asc'] = validHtmlStr($_REQUEST['sort_asc']); + } +} + +function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) { + $filter['query'] = ''; + $filter['sql'] = ''; + $filter['fields'] = ''; + + if ( isset($filter['terms']) && count($filter['terms']) ) { + for ( $i = 0; $i < count($filter['terms']); $i++ ) { + if ( isset($filter['terms'][$i]['cnj']) ) { + $filter['query'] .= $querySep."filter[terms][$i][cnj]=".urlencode($filter['terms'][$i]['cnj']); + $filter['sql'] .= " ".$filter['terms'][$i]['cnj']." "; + $filter['fields'] .= "\n"; + } + if ( isset($filter['terms'][$i]['obr']) ) { + $filter['query'] .= $querySep."filter[terms][$i][obr]=".urlencode($filter['terms'][$i]['obr']); + $filter['sql'] .= " ".str_repeat( "(", $filter['terms'][$i]['obr'] )." "; + $filter['fields'] .= "\n"; + } + if ( isset($filter['terms'][$i]['attr']) ) { + $filter['query'] .= $querySep."filter[terms][$i][attr]=".urlencode($filter['terms'][$i]['attr']); + $filter['fields'] .= "\n"; + switch ( $filter['terms'][$i]['attr'] ) { + case 'MonitorName': + $filter['sql'] .= 'M.'.preg_replace( '/^Monitor/', '', $filter['terms'][$i]['attr'] ); + break; + case 'DateTime': + $filter['sql'] .= "E.StartTime"; + break; + case 'Date': + $filter['sql'] .= "to_days( E.StartTime )"; + break; + case 'Time': + $filter['sql'] .= "extract( hour_second from E.StartTime )"; + break; + case 'Weekday': + $filter['sql'] .= "weekday( E.StartTime )"; + break; + case 'Id': + case 'Name': + case 'MonitorId': + case 'Length': + case 'Frames': + case 'AlarmFrames': + case 'TotScore': + case 'AvgScore': + case 'MaxScore': + case 'Cause': + case 'Notes': + case 'Archived': + $filter['sql'] .= 'E.'.$filter['terms'][$i]['attr']; + break; + case 'DiskPercent': + $filter['sql'] .= getDiskPercent(); + break; + case 'DiskBlocks': + $filter['sql'] .= getDiskBlocks(); + break; + case 'SystemLoad': + $filter['sql'] .= getLoad(); + break; + } + $valueList = array(); + foreach ( preg_split( '/["\'\s]*?,["\'\s]*?/', preg_replace( '/^["\']+?(.+)["\']+?$/', '$1', $filter['terms'][$i]['val'] ) ) as $value ) { + switch ( $filter['terms'][$i]['attr'] ) { + case 'MonitorName': + case 'Name': + case 'Cause': + case 'Notes': + $value = dbEscape($value); + break; + case 'DateTime': + $value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'"; + break; + case 'Date': + $value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )"; + break; + case 'Time': + $value = "extract( hour_second from '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )"; + break; + default : + $value = dbEscape($value); + break; + } + $valueList[] = $value; + } + + switch ( $filter['terms'][$i]['op'] ) { + case '=' : + case '!=' : + case '>=' : + case '>' : + case '<' : + case '<=' : + $filter['sql'] .= " ".$filter['terms'][$i]['op']." $value"; + break; + case '=~' : + $filter['sql'] .= " regexp ".$value; + break; + case '!~' : + $filter['sql'] .= " not regexp ".$value; + break; + case '=[]' : + $filter['sql'] .= " in (".join( ",", $valueList ).")"; + break; + case '![]' : + $filter['sql'] .= " not in (".join( ",", $valueList ).")"; + break; + } + + $filter['query'] .= $querySep."filter[terms][$i][op]=".urlencode($filter['terms'][$i]['op']); + $filter['fields'] .= "\n"; + $filter['query'] .= $querySep."filter[terms][$i][val]=".urlencode($filter['terms'][$i]['val']); + $filter['fields'] .= "\n"; + } + if ( isset($filter['terms'][$i]['cbr']) ) { + $filter['query'] .= $querySep."filter[terms][$i][cbr]=".urlencode($filter['terms'][$i]['cbr']); + $filter['sql'] .= " ".str_repeat( ")", $filter['terms'][$i]['cbr'] )." "; + $filter['fields'] .= "\n"; + } + } + if ( $filter['sql'] ) + $filter['sql'] = " and ( ".$filter['sql']." )"; + if ( $saveToSession ) { + $_SESSION['filter'] = $filter; + } + } +} + +function addFilterTerm( $filter, $position, $term=false ) { + if ( $position < 0 ) + $position = 0; + elseif( $position > count($filter['terms']) ) + $position = count($filter['terms']); + if ( $term && $position == 0 ) + unset( $term['cnj'] ); + array_splice( $filter['terms'], $position, 0, array( $term?$term:array() ) ); + + return( $filter ); +} + +function delFilterTerm( $filter, $position ) { + if ( $position < 0 ) + $position = 0; + elseif( $position >= count($filter['terms']) ) + $position = count($filter['terms']); + array_splice( $filter['terms'], $position, 1 ); + + return( $filter ); +} + +function getPagination( $pages, $page, $maxShortcuts, $query, $querySep='&' ) { + global $view; + + $pageText = ""; + if ( $pages > 1 ) { + if ( $page ) { + if ( $page < 0 ) + $page = 1; + if ( $page > $pages ) + $page = $pages; + + if ( $page > 1 ) { + if ( false && $page > 2 ) { + $pageText .= '<<'; + } + $pageText .= '<'; + + $newPages = array(); + $pagesUsed = array(); + $lo_exp = max(2,log($page-1)/log($maxShortcuts)); + for ( $i = 0; $i < $maxShortcuts; $i++ ) { + $newPage = round($page-pow($lo_exp,$i)); + if ( isset($pagesUsed[$newPage]) ) + continue; + if ( $newPage <= 1 ) + break; + $pagesUsed[$newPage] = true; + array_unshift( $newPages, $newPage ); + } + if ( !isset($pagesUsed[1]) ) + array_unshift( $newPages, 1 ); + + foreach ( $newPages as $newPage ) { + $pageText .= ''.$newPage.' '; + } + + } + $pageText .= '- '.$page.' -'; + if ( $page < $pages ) { + $newPages = array(); + $pagesUsed = array(); + $hi_exp = max(2,log($pages-$page)/log($maxShortcuts)); + for ( $i = 0; $i < $maxShortcuts; $i++ ) { + $newPage = round($page+pow($hi_exp,$i)); + if ( isset($pagesUsed[$newPage]) ) + continue; + if ( $newPage > $pages ) + break; + $pagesUsed[$newPage] = true; + array_push( $newPages, $newPage ); + } + if ( !isset($pagesUsed[$pages]) ) + array_push( $newPages, $pages ); + + foreach ( $newPages as $newPage ) { + $pageText .= ' '.$newPage.''; + } + $pageText .= '>'; + if ( false && $page < ($pages-1) ) { + $pageText .= '>>'; + } + } + } + } + return( $pageText ); +} + +function sortHeader( $field, $querySep='&' ) { + global $view; + return( '?view='.$view.$querySep.'page=1'.$_REQUEST['filter']['query'].$querySep.'sort_field='.$field.$querySep.'sort_asc='.($_REQUEST['sort_field'] == $field?!$_REQUEST['sort_asc']:0).$querySep.'limit='.$_REQUEST['limit'] ); +} + +function sortTag( $field ) { + if ( $_REQUEST['sort_field'] == $field ) + if ( $_REQUEST['sort_asc'] ) + return( "(^)" ); else - $midSql = ''; - return( $midSql ); + return( "(v)" ); + return( false ); } -function parseSort( $saveToSession=false, $querySep='&' ) -{ - global $sortQuery, $sortColumn, $sortOrder; // Outputs - - if ( empty($_REQUEST['sort_field']) ) - { - $_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD; - $_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc"); - } - switch( $_REQUEST['sort_field'] ) - { - case 'Id' : - $sortColumn = "E.Id"; - break; - case 'MonitorName' : - $sortColumn = "M.Name"; - break; - case 'Name' : - $sortColumn = "E.Name"; - break; - case 'Cause' : - $sortColumn = "E.Cause"; - break; - case 'DateTime' : - $_REQUEST['sort_field'] = 'StartTime'; - case 'StartTime' : - $sortColumn = "E.StartTime"; - break; - case 'Length' : - $sortColumn = "E.Length"; - break; - case 'Frames' : - $sortColumn = "E.Frames"; - break; - case 'AlarmFrames' : - $sortColumn = "E.AlarmFrames"; - break; - case 'TotScore' : - $sortColumn = "E.TotScore"; - break; - case 'AvgScore' : - $sortColumn = "E.AvgScore"; - break; - case 'MaxScore' : - $sortColumn = "E.MaxScore"; - break; - default: - $sortColumn = "E.StartTime"; - break; - } - $sortOrder = $_REQUEST['sort_asc']?"asc":"desc"; - if ( !$_REQUEST['sort_asc'] ) - $_REQUEST['sort_asc'] = 0; - $sortQuery = $querySep."sort_field=".validHtmlStr($_REQUEST['sort_field']).$querySep."sort_asc=".validHtmlStr($_REQUEST['sort_asc']); - if ( !isset($_REQUEST['limit']) ) - $_REQUEST['limit'] = ""; - if ( $saveToSession ) - { - $_SESSION['sort_field'] = validHtmlStr($_REQUEST['sort_field']); - $_SESSION['sort_asc'] = validHtmlStr($_REQUEST['sort_asc']); - } +function getLoad() { + $load = sys_getloadavg(); + return( $load[0] ); } -function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) -{ - $filter['query'] = ''; - $filter['sql'] = ''; - $filter['fields'] = ''; - - if ( isset($filter['terms']) && count($filter['terms']) ) - { - for ( $i = 0; $i < count($filter['terms']); $i++ ) - { - if ( isset($filter['terms'][$i]['cnj']) ) - { - $filter['query'] .= $querySep."filter[terms][$i][cnj]=".urlencode($filter['terms'][$i]['cnj']); - $filter['sql'] .= " ".$filter['terms'][$i]['cnj']." "; - $filter['fields'] .= "\n"; - } - if ( isset($filter['terms'][$i]['obr']) ) - { - $filter['query'] .= $querySep."filter[terms][$i][obr]=".urlencode($filter['terms'][$i]['obr']); - $filter['sql'] .= " ".str_repeat( "(", $filter['terms'][$i]['obr'] )." "; - $filter['fields'] .= "\n"; - } - if ( isset($filter['terms'][$i]['attr']) ) - { - $filter['query'] .= $querySep."filter[terms][$i][attr]=".urlencode($filter['terms'][$i]['attr']); - $filter['fields'] .= "\n"; - switch ( $filter['terms'][$i]['attr'] ) - { - case 'MonitorName': - $filter['sql'] .= 'M.'.preg_replace( '/^Monitor/', '', $filter['terms'][$i]['attr'] ); - break; - case 'DateTime': - $filter['sql'] .= "E.StartTime"; - break; - case 'Date': - $filter['sql'] .= "to_days( E.StartTime )"; - break; - case 'Time': - $filter['sql'] .= "extract( hour_second from E.StartTime )"; - break; - case 'Weekday': - $filter['sql'] .= "weekday( E.StartTime )"; - break; - case 'Id': - case 'Name': - case 'MonitorId': - case 'Length': - case 'Frames': - case 'AlarmFrames': - case 'TotScore': - case 'AvgScore': - case 'MaxScore': - case 'Cause': - case 'Notes': - case 'Archived': - $filter['sql'] .= 'E.'.$filter['terms'][$i]['attr']; - break; - case 'DiskPercent': - $filter['sql'] .= getDiskPercent(); - break; - case 'DiskBlocks': - $filter['sql'] .= getDiskBlocks(); - break; - case 'SystemLoad': - $filter['sql'] .= getLoad(); - break; - } - $valueList = array(); - foreach ( preg_split( '/["\'\s]*?,["\'\s]*?/', preg_replace( '/^["\']+?(.+)["\']+?$/', '$1', $filter['terms'][$i]['val'] ) ) as $value ) - { - switch ( $filter['terms'][$i]['attr'] ) - { - case 'MonitorName': - case 'Name': - case 'Cause': - case 'Notes': - $value = dbEscape($value); - break; - case 'DateTime': - $value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'"; - break; - case 'Date': - $value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )"; - break; - case 'Time': - $value = "extract( hour_second from '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )"; - break; - default : - $value = dbEscape($value); - break; - } - $valueList[] = $value; - } - - switch ( $filter['terms'][$i]['op'] ) - { - case '=' : - case '!=' : - case '>=' : - case '>' : - case '<' : - case '<=' : - $filter['sql'] .= " ".$filter['terms'][$i]['op']." $value"; - break; - case '=~' : - $filter['sql'] .= " regexp ".$value; - break; - case '!~' : - $filter['sql'] .= " not regexp ".$value; - break; - case '=[]' : - $filter['sql'] .= " in (".join( ",", $valueList ).")"; - break; - case '![]' : - $filter['sql'] .= " not in (".join( ",", $valueList ).")"; - break; - } - - $filter['query'] .= $querySep."filter[terms][$i][op]=".urlencode($filter['terms'][$i]['op']); - $filter['fields'] .= "\n"; - $filter['query'] .= $querySep."filter[terms][$i][val]=".urlencode($filter['terms'][$i]['val']); - $filter['fields'] .= "\n"; - } - if ( isset($filter['terms'][$i]['cbr']) ) - { - $filter['query'] .= $querySep."filter[terms][$i][cbr]=".urlencode($filter['terms'][$i]['cbr']); - $filter['sql'] .= " ".str_repeat( ")", $filter['terms'][$i]['cbr'] )." "; - $filter['fields'] .= "\n"; - } - } - if ( $filter['sql'] ) - $filter['sql'] = " and ( ".$filter['sql']." )"; - if ( $saveToSession ) - { - $_SESSION['filter'] = $filter; - } - } +function getDiskPercent() { + $total = disk_total_space(ZM_DIR_EVENTS); + if ( ! $total ) { + Error("disk_total_space returned false for " . ZM_DIR_EVENTS ); + return 0; + } + $free = disk_free_space(ZM_DIR_EVENTS); + if ( ! $free ) { + Error("disk_free_space returned false for " . ZM_DIR_EVENTS ); + } + $space = round(($total - $free) / $total * 100); + return( $space ); } -function addFilterTerm( $filter, $position, $term=false ) -{ - if ( $position < 0 ) - $position = 0; - elseif( $position > count($filter['terms']) ) - $position = count($filter['terms']); - if ( $term && $position == 0 ) - unset( $term['cnj'] ); - array_splice( $filter['terms'], $position, 0, array( $term?$term:array() ) ); - - return( $filter ); -} - -function delFilterTerm( $filter, $position ) -{ - if ( $position < 0 ) - $position = 0; - elseif( $position >= count($filter['terms']) ) - $position = count($filter['terms']); - array_splice( $filter['terms'], $position, 1 ); - - return( $filter ); -} - -function getPagination( $pages, $page, $maxShortcuts, $query, $querySep='&' ) -{ - global $view; - - $pageText = ""; - if ( $pages > 1 ) - { - if ( $page ) - { - if ( $page < 0 ) - $page = 1; - if ( $page > $pages ) - $page = $pages; - - if ( $page > 1 ) - { - if ( false && $page > 2 ) - { - $pageText .= '<<'; - } - $pageText .= '<'; - - $newPages = array(); - $pagesUsed = array(); - $lo_exp = max(2,log($page-1)/log($maxShortcuts)); - for ( $i = 0; $i < $maxShortcuts; $i++ ) - { - $newPage = round($page-pow($lo_exp,$i)); - if ( isset($pagesUsed[$newPage]) ) - continue; - if ( $newPage <= 1 ) - break; - $pagesUsed[$newPage] = true; - array_unshift( $newPages, $newPage ); - } - if ( !isset($pagesUsed[1]) ) - array_unshift( $newPages, 1 ); - - foreach ( $newPages as $newPage ) - { - $pageText .= ''.$newPage.' '; - } - - } - $pageText .= '- '.$page.' -'; - if ( $page < $pages ) - { - $newPages = array(); - $pagesUsed = array(); - $hi_exp = max(2,log($pages-$page)/log($maxShortcuts)); - for ( $i = 0; $i < $maxShortcuts; $i++ ) - { - $newPage = round($page+pow($hi_exp,$i)); - if ( isset($pagesUsed[$newPage]) ) - continue; - if ( $newPage > $pages ) - break; - $pagesUsed[$newPage] = true; - array_push( $newPages, $newPage ); - } - if ( !isset($pagesUsed[$pages]) ) - array_push( $newPages, $pages ); - - foreach ( $newPages as $newPage ) - { - $pageText .= ' '.$newPage.''; - } - $pageText .= '>'; - if ( false && $page < ($pages-1) ) - { - $pageText .= '>>'; - } - } - } - } - return( $pageText ); -} - -function sortHeader( $field, $querySep='&' ) -{ - global $view; - return( '?view='.$view.$querySep.'page=1'.$_REQUEST['filter']['query'].$querySep.'sort_field='.$field.$querySep.'sort_asc='.($_REQUEST['sort_field'] == $field?!$_REQUEST['sort_asc']:0).$querySep.'limit='.$_REQUEST['limit'] ); -} - -function sortTag( $field ) -{ - if ( $_REQUEST['sort_field'] == $field ) - if ( $_REQUEST['sort_asc'] ) - return( "(^)" ); - else - return( "(v)" ); - return( false ); -} - -function getLoad() -{ - $load = sys_getloadavg(); - return( $load[0] ); -} - -function getDiskPercent() -{ - $total = disk_total_space(ZM_DIR_EVENTS); - if ( ! $total ) { - Error("disk_total_space returned false for " . ZM_DIR_EVENTS ); - return 0; - } - $free = disk_free_space(ZM_DIR_EVENTS); - if ( ! $free ) { - Error("disk_free_space returned false for " . ZM_DIR_EVENTS ); - } - $space = round(($total - $free) / $total * 100); - return( $space ); -} - -function getDiskBlocks() -{ - $df = shell_exec( 'df '.ZM_DIR_EVENTS ); - $space = -1; - if ( preg_match( '/\s(\d+)\s+\d+\s+\d+%/ms', $df, $matches ) ) - $space = $matches[1]; - return( $space ); +function getDiskBlocks() { + $df = shell_exec( 'df '.ZM_DIR_EVENTS ); + $space = -1; + if ( preg_match( '/\s(\d+)\s+\d+\s+\d+%/ms', $df, $matches ) ) + $space = $matches[1]; + return( $space ); } // Function to fix a problem whereby the built in PHP session handling // features want to put the sid as a hidden field after the form or // fieldset tag, neither of which will work with strict XHTML Basic. -function sidField() -{ - if ( SID ) - { - list( $sessname, $sessid ) = explode( "=", SID ); +function sidField() { + if ( SID ) { + list( $sessname, $sessid ) = explode( "=", SID ); ?> - + "; + // Checking if bounding boxes intersect + if ( $max_x1 < $min_x2 || $max_x2 < $min_x1 ||$max_y1 < $min_y2 || $max_y2 < $min_y1 ) { + if ( $debug ) echo "Not intersecting, out of bounds
"; + return( false ); + } + + $dx1 = $line1[1]['x'] - $line1[0]['x']; + $dy1 = $line1[1]['y'] - $line1[0]['y']; + $dx2 = $line2[1]['x'] - $line2[0]['x']; + $dy2 = $line2[1]['y'] - $line2[0]['y']; + + if ( $dx1 ) { + $m1 = $dy1/$dx1; + $b1 = $line1[0]['y'] - ($m1 * $line1[0]['x']); + } else { + $b1 = $line1[0]['y']; + } + if ( $dx2 ) { + $m2 = $dy2/$dx2; + $b2 = $line2[0]['y'] - ($m2 * $line2[0]['x']); + } else { + $b2 = $line2[0]['y']; + } + + if ( $dx1 && $dx2 ) { // Both not vertical + if ( $m1 != $m2 ) { // Not parallel or colinear + $x = ( $b2 - $b1 ) / ( $m1 - $m2 ); + + if ( $x >= $min_x1 && $x <= $max_x1 && $x >= $min_x2 && $x <= $max_x2 ) { + if ( $debug ) echo "Intersecting, at x $x
"; + return( true ); + } else { + if ( $debug ) echo "Not intersecting, out of range at x $x
"; return( false ); + } + } elseif ( $b1 == $b2 ) { + // Colinear, must overlap due to box check, intersect? + if ( $debug ) echo "Intersecting, colinear
"; + return( true ); + } else { + // Parallel + if ( $debug ) echo "Not intersecting, parallel
"; + return( false ); } - - $dx1 = $line1[1]['x'] - $line1[0]['x']; - $dy1 = $line1[1]['y'] - $line1[0]['y']; - $dx2 = $line2[1]['x'] - $line2[0]['x']; - $dy2 = $line2[1]['y'] - $line2[0]['y']; - - if ( $dx1 ) - { - $m1 = $dy1/$dx1; - $b1 = $line1[0]['y'] - ($m1 * $line1[0]['x']); + } elseif ( !$dx1 ) { // Line 1 is vertical + $y = ( $m2 * $line1[0]['x'] ) * $b2; + if ( $y >= $min_y1 && $y <= $max_y1 ) { + if ( $debug ) echo "Intersecting, at y $y
"; + return( true ); + } else { + if ( $debug ) echo "Not intersecting, out of range at y $y
"; + return( false ); } - else - { - $b1 = $line1[0]['y']; + } elseif ( !$dx2 ) { // Line 2 is vertical + $y = ( $m1 * $line2[0]['x'] ) * $b1; + if ( $y >= $min_y2 && $y <= $max_y2 ) { + if ( $debug ) echo "Intersecting, at y $y
"; + return( true ); + } else { + if ( $debug ) echo "Not intersecting, out of range at y $y
"; + return( false ); } - if ( $dx2 ) - { - $m2 = $dy2/$dx2; - $b2 = $line2[0]['y'] - ($m2 * $line2[0]['x']); + } else { // Both lines are vertical + if ( $line1[0]['x'] == $line2[0]['x'] ) { + // Colinear, must overlap due to box check, intersect? + if ( $debug ) echo "Intersecting, vertical, colinear
"; + return( true ); + } else { + // Parallel + if ( $debug ) echo "Not intersecting, vertical, parallel
"; + return( false ); } - else - { - $b2 = $line2[0]['y']; - } - - if ( $dx1 && $dx2 ) // Both not vertical - { - if ( $m1 != $m2 ) // Not parallel or colinear - { - $x = ( $b2 - $b1 ) / ( $m1 - $m2 ); - - if ( $x >= $min_x1 && $x <= $max_x1 && $x >= $min_x2 && $x <= $max_x2 ) - { - if ( $debug ) echo "Intersecting, at x $x
"; - return( true ); - } - else - { - if ( $debug ) echo "Not intersecting, out of range at x $x
"; - return( false ); - } - } - elseif ( $b1 == $b2 ) - { - // Colinear, must overlap due to box check, intersect? - if ( $debug ) echo "Intersecting, colinear
"; - return( true ); - } - else - { - // Parallel - if ( $debug ) echo "Not intersecting, parallel
"; - return( false ); - } - } - elseif ( !$dx1 ) // Line 1 is vertical - { - $y = ( $m2 * $line1[0]['x'] ) * $b2; - if ( $y >= $min_y1 && $y <= $max_y1 ) - { - if ( $debug ) echo "Intersecting, at y $y
"; - return( true ); - } - else - { - if ( $debug ) echo "Not intersecting, out of range at y $y
"; - return( false ); - } - } - elseif ( !$dx2 ) // Line 2 is vertical - { - $y = ( $m1 * $line2[0]['x'] ) * $b1; - if ( $y >= $min_y2 && $y <= $max_y2 ) - { - if ( $debug ) echo "Intersecting, at y $y
"; - return( true ); - } - else - { - if ( $debug ) echo "Not intersecting, out of range at y $y
"; - return( false ); - } - } - else // Both lines are vertical - { - if ( $line1[0]['x'] == $line2[0]['x'] ) - { - // Colinear, must overlap due to box check, intersect? - if ( $debug ) echo "Intersecting, vertical, colinear
"; - return( true ); - } - else - { - // Parallel - if ( $debug ) echo "Not intersecting, vertical, parallel
"; - return( false ); - } - } - if ( $debug ) echo "Whoops, unexpected scenario
"; - return( false ); + } + if ( $debug ) echo "Whoops, unexpected scenario
"; + return( false ); } -function isSelfIntersecting( $points ) -{ - global $debug; +function isSelfIntersecting( $points ) { + global $debug; - $n_coords = count($points); - $edges = array(); - for ( $j = 0, $i = $n_coords-1; $j < $n_coords; $i = $j++ ) - { - $edges[] = array( $points[$i], $points[$j] ); - } + $n_coords = count($points); + $edges = array(); + for ( $j = 0, $i = $n_coords-1; $j < $n_coords; $i = $j++ ) { + $edges[] = array( $points[$i], $points[$j] ); + } - for ( $i = 0; $i <= ($n_coords-2); $i++ ) - { - for ( $j = $i+2; $j < $n_coords+min(0,$i-1); $j++ ) - { - if ( $debug ) echo "Checking $i and $j
"; - if ( linesIntersect( $edges[$i], $edges[$j] ) ) - { - if ( $debug ) echo "Lines $i and $j intersect
"; - return( true ); - } - } + for ( $i = 0; $i <= ($n_coords-2); $i++ ) { + for ( $j = $i+2; $j < $n_coords+min(0,$i-1); $j++ ) { + if ( $debug ) echo "Checking $i and $j
"; + if ( linesIntersect( $edges[$i], $edges[$j] ) ) { + if ( $debug ) echo "Lines $i and $j intersect
"; + return( true ); + } } - return( false ); + } + return( false ); } -function getPolyCentre( $points, $area=0 ) -{ - $cx = 0.0; - $cy = 0.0; - if ( !$area ) - $area = getPolyArea( $points ); - for ( $i = 0, $j = count($points)-1; $i < count($points); $j = $i++ ) - { - $ct = ($points[$i]['x'] * $points[$j]['y']) - ($points[$j]['x'] * $points[$i]['y']); - $cx += ($points[$i]['x'] + $points[$j]['x']) * ct; - $cy += ($points[$i]['y'] + $points[$j]['y']) * ct; - } - $cx = intval(round(abs($cx/(6.0*$area)))); - $cy = intval(round(abs($cy/(6.0*$area)))); - printf( "X:%cx, Y:$cy
" ); - return( array( 'x'=>$cx, 'y'=>$cy ) ); +function getPolyCentre( $points, $area=0 ) { + $cx = 0.0; + $cy = 0.0; + if ( !$area ) + $area = getPolyArea( $points ); + for ( $i = 0, $j = count($points)-1; $i < count($points); $j = $i++ ) { + $ct = ($points[$i]['x'] * $points[$j]['y']) - ($points[$j]['x'] * $points[$i]['y']); + $cx += ($points[$i]['x'] + $points[$j]['x']) * ct; + $cy += ($points[$i]['y'] + $points[$j]['y']) * ct; + } + $cx = intval(round(abs($cx/(6.0*$area)))); + $cy = intval(round(abs($cy/(6.0*$area)))); + printf( "X:%cx, Y:$cy
" ); + return( array( 'x'=>$cx, 'y'=>$cy ) ); } -function _CompareXY( $a, $b ) -{ - if ( $a['min_y'] == $b['min_y'] ) - return( intval($a['min_x'] - $b['min_x']) ); - else - return( intval($a['min_y'] - $b['min_y']) ); -} - -function _CompareX( $a, $b ) -{ +function _CompareXY( $a, $b ) { + if ( $a['min_y'] == $b['min_y'] ) return( intval($a['min_x'] - $b['min_x']) ); + else + return( intval($a['min_y'] - $b['min_y']) ); } -function getPolyArea( $points ) -{ - global $debug; +function _CompareX( $a, $b ) { + return( intval($a['min_x'] - $b['min_x']) ); +} - $n_coords = count($points); - $global_edges = array(); - for ( $j = 0, $i = $n_coords-1; $j < $n_coords; $i = $j++ ) - { - $x1 = $points[$i]['x']; - $x2 = $points[$j]['x']; - $y1 = $points[$i]['y']; - $y2 = $points[$j]['y']; +function getPolyArea( $points ) { + global $debug; - //printf( "x1:%d,y1:%d x2:%d,y2:%d\n", x1, y1, x2, y2 ); - if ( $y1 == $y2 ) - continue; + $n_coords = count($points); + $global_edges = array(); + for ( $j = 0, $i = $n_coords-1; $j < $n_coords; $i = $j++ ) { + $x1 = $points[$i]['x']; + $x2 = $points[$j]['x']; + $y1 = $points[$i]['y']; + $y2 = $points[$j]['y']; - $dx = $x2 - $x1; - $dy = $y2 - $y1; + //printf( "x1:%d,y1:%d x2:%d,y2:%d\n", x1, y1, x2, y2 ); + if ( $y1 == $y2 ) + continue; - $global_edges[] = array( - "min_y" => $y1<$y2?$y1:$y2, - "max_y" => ($y1<$y2?$y2:$y1)+1, - "min_x" => $y1<$y2?$x1:$x2, - "_1_m" => $dx/$dy, + $dx = $x2 - $x1; + $dy = $y2 - $y1; + + $global_edges[] = array( + "min_y" => $y1<$y2?$y1:$y2, + "max_y" => ($y1<$y2?$y2:$y1)+1, + "min_x" => $y1<$y2?$x1:$x2, + "_1_m" => $dx/$dy, ); + } + + usort( $global_edges, "_CompareXY" ); + + if ( $debug ) { + for ( $i = 0; $i < count($global_edges); $i++ ) { + printf( "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f
", $i, $global_edges[$i]['min_y'], $global_edges[$i]['max_y'], $global_edges[$i]['min_x'], $global_edges[$i]['_1_m'] ); } + } - usort( $global_edges, "_CompareXY" ); - - if ( $debug ) - { - for ( $i = 0; $i < count($global_edges); $i++ ) - { - printf( "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f
", $i, $global_edges[$i]['min_y'], $global_edges[$i]['max_y'], $global_edges[$i]['min_x'], $global_edges[$i]['_1_m'] ); - } + $area = 0.0; + $active_edges = array(); + $y = $global_edges[0]['min_y']; + do { + for ( $i = 0; $i < count($global_edges); $i++ ) { + if ( $global_edges[$i]['min_y'] == $y ) { + if ( $debug ) printf( "Moving global edge
" ); + $active_edges[] = $global_edges[$i]; + array_splice( $global_edges, $i, 1 ); + $i--; + } else { + break; + } } - - $area = 0.0; - $active_edges = array(); - $y = $global_edges[0]['min_y']; - do - { - for ( $i = 0; $i < count($global_edges); $i++ ) - { - if ( $global_edges[$i]['min_y'] == $y ) - { - if ( $debug ) printf( "Moving global edge
" ); - $active_edges[] = $global_edges[$i]; - array_splice( $global_edges, $i, 1 ); - $i--; - } - else - { - break; - } - } - usort( $active_edges, "_CompareX" ); - if ( $debug ) - { - for ( $i = 0; $i < count($active_edges); $i++ ) - { - printf( "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f
", $y, $i, $active_edges[$i]['min_y'], $active_edges[$i]['max_y'], $active_edges[$i]['min_x'], $active_edges[$i]['_1_m'] ); - } - } - $last_x = 0; - $row_area = 0; - $parity = false; - for ( $i = 0; $i < count($active_edges); $i++ ) - { - $x = intval(round($active_edges[$i]['min_x'])); - if ( $parity ) - { - $row_area += ($x - $last_x)+1; - $area += $row_area; - } - if ( $active_edges[$i]['max_y'] != $y ) - $parity = !$parity; - $last_x = $x; - } - if ( $debug ) printf( "%d: Area:%d
", $y, $row_area ); - $y++; - for ( $i = 0; $i < count($active_edges); $i++ ) - { - if ( $y >= $active_edges[$i]['max_y'] ) // Or >= as per sheets - { - if ( $debug ) printf( "Deleting active_edge
" ); - array_splice( $active_edges, $i, 1 ); - $i--; - } - else - { - $active_edges[$i]['min_x'] += $active_edges[$i]['_1_m']; - } - } - } while ( count($global_edges) || count($active_edges) ); - if ( $debug ) printf( "Area:%d
", $area ); - return( $area ); + usort( $active_edges, "_CompareX" ); + if ( $debug ) { + for ( $i = 0; $i < count($active_edges); $i++ ) { + printf( "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f
", $y, $i, $active_edges[$i]['min_y'], $active_edges[$i]['max_y'], $active_edges[$i]['min_x'], $active_edges[$i]['_1_m'] ); + } + } + $last_x = 0; + $row_area = 0; + $parity = false; + for ( $i = 0; $i < count($active_edges); $i++ ) { + $x = intval(round($active_edges[$i]['min_x'])); + if ( $parity ) { + $row_area += ($x - $last_x)+1; + $area += $row_area; + } + if ( $active_edges[$i]['max_y'] != $y ) + $parity = !$parity; + $last_x = $x; + } + if ( $debug ) printf( "%d: Area:%d
", $y, $row_area ); + $y++; + for ( $i = 0; $i < count($active_edges); $i++ ) { + if ( $y >= $active_edges[$i]['max_y'] ) { // Or >= as per sheets + if ( $debug ) printf( "Deleting active_edge
" ); + array_splice( $active_edges, $i, 1 ); + $i--; + } else { + $active_edges[$i]['min_x'] += $active_edges[$i]['_1_m']; + } + } + } while ( count($global_edges) || count($active_edges) ); + if ( $debug ) printf( "Area:%d
", $area ); + return( $area ); } -function getPolyAreaOld( $points ) -{ - $area = 0.0; - $edge = 0.0; - for ( $i = 0, $j = count($points)-1; $i < count($points); $j = $i++ ) - { - $x_diff = ($points[$i]['x'] - $points[$j]['x']); - $y_diff = ($points[$i]['y'] - $points[$j]['y']); - $y_sum = ($points[$i]['y'] + $points[$j]['y']); - $trap_edge = sqrt(pow(abs($x_diff)+1,2) + pow(abs($y_diff)+1,2) ); - $edge += $trap_edge; - $trap_area = ($x_diff * $y_sum ); - $area += $trap_area; - printf( "%d->%d, %d-%d=%.2f, %d+%d=%.2f(%.2f), %.2f, %.2f
", i, j, $points[$i]['x'], $points[$j]['x'], $x_diff, $points[$i]['y'], $points[$j]['y'], $y_sum, $y_diff, $trap_area, $trap_edge ); - } - $edge = intval(round(abs($edge))); - $area = intval(round((abs($area)+$edge)/2)); - echo "E:$edge
"; - echo "A:$area
"; - return( $area ); +function getPolyAreaOld( $points ) { + $area = 0.0; + $edge = 0.0; + for ( $i = 0, $j = count($points)-1; $i < count($points); $j = $i++ ) { + $x_diff = ($points[$i]['x'] - $points[$j]['x']); + $y_diff = ($points[$i]['y'] - $points[$j]['y']); + $y_sum = ($points[$i]['y'] + $points[$j]['y']); + $trap_edge = sqrt(pow(abs($x_diff)+1,2) + pow(abs($y_diff)+1,2) ); + $edge += $trap_edge; + $trap_area = ($x_diff * $y_sum ); + $area += $trap_area; + printf( "%d->%d, %d-%d=%.2f, %d+%d=%.2f(%.2f), %.2f, %.2f
", i, j, $points[$i]['x'], $points[$j]['x'], $x_diff, $points[$i]['y'], $points[$j]['y'], $y_sum, $y_diff, $trap_area, $trap_edge ); + } + $edge = intval(round(abs($edge))); + $area = intval(round((abs($area)+$edge)/2)); + echo "E:$edge
"; + echo "A:$area
"; + return( $area ); } -function mapCoords( $a ) -{ - return( $a['x'].",".$a['y'] ); +function mapCoords( $a ) { + return( $a['x'].",".$a['y'] ); } -function pointsToCoords( $points ) -{ - return( join( " ", array_map( "mapCoords", $points ) ) ); +function pointsToCoords( $points ) { + return( join( " ", array_map( "mapCoords", $points ) ) ); } -function coordsToPoints( $coords ) -{ - $points = array(); - if ( preg_match_all( '/(\d+,\d+)+/', $coords, $matches ) ) - { - for ( $i = 0; $i < count($matches[1]); $i++ ) - { - if ( preg_match( '/(\d+),(\d+)/', $matches[1][$i], $cmatches ) ) - { - $points[] = array( 'x'=>$cmatches[1], 'y'=>$cmatches[2] ); - } - else - { - echo( "Bogus coordinates '".$matches[$i]."'" ); - return( false ); - } - } - } - else - { - echo( "Bogus coordinate string '$coords'" ); +function coordsToPoints( $coords ) { + $points = array(); + if ( preg_match_all( '/(\d+,\d+)+/', $coords, $matches ) ) { + for ( $i = 0; $i < count($matches[1]); $i++ ) { + if ( preg_match( '/(\d+),(\d+)/', $matches[1][$i], $cmatches ) ) { + $points[] = array( 'x'=>$cmatches[1], 'y'=>$cmatches[2] ); + } else { + echo( "Bogus coordinates '".$matches[$i]."'" ); return( false ); + } } - return( $points ); + } else { + echo( "Bogus coordinate string '$coords'" ); + return( false ); + } + return( $points ); } -function getLanguages() -{ - $langs = array(); - foreach ( glob("lang/*_*.php") as $file ) - { - preg_match( '/([^\/]+_.+)\.php/', $file, $matches ); - $langs[$matches[1]] = $matches[1]; +function getLanguages() { + $langs = array(); + foreach ( glob("lang/*_*.php") as $file ) { + preg_match( '/([^\/]+_.+)\.php/', $file, $matches ); + $langs[$matches[1]] = $matches[1]; + } + return( $langs ); +} + +function trimString( $string, $length ) { + return( preg_replace( '/^(.{'.$length.',}?)\b.*$/', '\\1…', $string ) ); +} + +function monitorIdsToNames( $ids ) { + global $mITN_monitors; + if ( !$mITN_monitors ) { + $sql = "select Id, Name from Monitors"; + foreach( dbFetchAll( $sql ) as $monitor ) { + $mITN_monitors[$monitor['Id']] = $monitor; } - return( $langs ); -} - -function trimString( $string, $length ) -{ - return( preg_replace( '/^(.{'.$length.',}?)\b.*$/', '\\1…', $string ) ); -} - -function monitorIdsToNames( $ids ) -{ - global $mITN_monitors; - if ( !$mITN_monitors ) - { - $sql = "select Id, Name from Monitors"; - foreach( dbFetchAll( $sql ) as $monitor ) - { - $mITN_monitors[$monitor['Id']] = $monitor; - } + } + $names = array(); + foreach ( preg_split( '/\s*,\s*/', $ids ) as $id ) { + if ( visibleMonitor( $id ) ) { + if ( isset($mITN_monitors[$id]) ) { + $names[] = $mITN_monitors[$id]['Name']; + } } - $names = array(); - foreach ( preg_split( '/\s*,\s*/', $ids ) as $id ) - { - if ( visibleMonitor( $id ) ) - { - if ( isset($mITN_monitors[$id]) ) - { - $names[] = $mITN_monitors[$id]['Name']; - } - } - } - $name_string = join( ', ', $names ); - return( $name_string ); + } + $name_string = join( ', ', $names ); + return( $name_string ); } -function initX10Status() -{ - global $x10_status; +function initX10Status() { + global $x10_status; - if ( !isset($x10_status) ) - { - $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 ); - if ( $socket < 0 ) - { - Fatal( "socket_create() failed: ".socket_strerror($socket) ); - } - $sock_file = ZM_PATH_SOCKS.'/zmx10.sock'; - if ( @socket_connect( $socket, $sock_file ) ) - { - $command = "status"; - if ( !socket_write( $socket, $command ) ) - { - Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) ); - } - socket_shutdown( $socket, 1 ); - $x10Output = ""; - while ( $x10Response = socket_read( $socket, 256 ) ) - { - $x10Output .= $x10Response; - } - socket_close( $socket ); - } - else - { - // Can't connect so use script - $command = ZM_PATH_BIN."/zmx10.pl --command status"; - //$command .= " 2>/dev/null >&- <&- >/dev/null"; - - $x10Output = exec( escapeshellcmd( $command ) ); - } - foreach ( explode( "\n", $x10Output ) as $x10Response ) - { - if ( preg_match( "/^(\d+)\s+(.+)$/", $x10Response, $matches ) ) - { - $x10_status[$matches[1]] = $matches[2]; - } - } - } -} - -function getDeviceStatusX10( $key ) -{ - global $x10_status; - - initX10Status(); - - if ( empty($x10_status[$key]) || !($status = $x10_status[$key]) ) - $status = "unknown"; - return( $status ); -} - -function setDeviceStatusX10( $key, $status ) -{ + if ( !isset($x10_status) ) { $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 ); - if ( $socket < 0 ) - { - Fatal( "socket_create() failed: ".socket_strerror($socket) ); + if ( $socket < 0 ) { + Fatal( "socket_create() failed: ".socket_strerror($socket) ); } $sock_file = ZM_PATH_SOCKS.'/zmx10.sock'; - if ( @socket_connect( $socket, $sock_file ) ) - { - $command = "$status;$key"; - if ( !socket_write( $socket, $command ) ) - { - Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) ); - } - socket_shutdown( $socket, 1 ); - $x10Response = socket_read( $socket, 256 ); - socket_close( $socket ); + if ( @socket_connect( $socket, $sock_file ) ) { + $command = "status"; + if ( !socket_write( $socket, $command ) ) { + Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) ); + } + socket_shutdown( $socket, 1 ); + $x10Output = ""; + while ( $x10Response = socket_read( $socket, 256 ) ) { + $x10Output .= $x10Response; + } + socket_close( $socket ); + } else { + // Can't connect so use script + $command = ZM_PATH_BIN."/zmx10.pl --command status"; + //$command .= " 2>/dev/null >&- <&- >/dev/null"; + + $x10Output = exec( escapeshellcmd( $command ) ); } - else - { - // Can't connect so use script - $command = ZM_PATH_BIN.'/zmx10.pl --command '.escapeshellarg( $status ); - $command .= ' --unit-code '.escapeshellarg( $key ); - //$command .= " 2>/dev/null >&- <&- >/dev/null"; - $x10Response = exec( $command ); + foreach ( explode( "\n", $x10Output ) as $x10Response ) { + if ( preg_match( "/^(\d+)\s+(.+)$/", $x10Response, $matches ) ) { + $x10_status[$matches[1]] = $matches[2]; + } } - if ( preg_match( '/^'.$key.'\s+(.*)/', $x10Response, $matches ) ) - $status = $matches[1]; - else - $status = "unknown"; - return( $status ); + } } -function logState() -{ - $state = 'ok'; +function getDeviceStatusX10( $key ) { + global $x10_status; - $levelCounts = array( - Logger::FATAL => array( ZM_LOG_ALERT_FAT_COUNT, ZM_LOG_ALARM_FAT_COUNT ), - Logger::ERROR => array( ZM_LOG_ALERT_ERR_COUNT, ZM_LOG_ALARM_ERR_COUNT ), - Logger::WARNING => array( ZM_LOG_ALERT_WAR_COUNT, ZM_LOG_ALARM_WAR_COUNT ), - ); + initX10Status(); - $sql = "select Level, count(Level) as LevelCount from Logs where Level < ".Logger::INFO." and TimeKey > unix_timestamp(now() - interval ".ZM_LOG_CHECK_PERIOD." second) group by Level order by Level asc"; - $counts = dbFetchAll( $sql ); - - foreach ( $counts as $count ) - { - if ( $count['Level'] <= Logger::PANIC ) - $count['Level'] = Logger::FATAL; - if ( !($levelCount = $levelCounts[$count['Level']]) ) - { - Error( "Unexpected Log level ".$count['Level'] ); - next; - } - if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) - { - $state = 'alarm'; - break; - } - elseif ( $levelCount[0] && $count['LevelCount'] >= $levelCount[0] ) - { - $state = 'alert'; - } - } - return( $state ); + if ( empty($x10_status[$key]) || !($status = $x10_status[$key]) ) + $status = "unknown"; + return( $status ); } -function isVector ( &$array ) -{ - $next_key = 0; - foreach ( array_keys($array) as $key ) - { - if ( !is_int( $key ) ) - return( false ); - if ( $key != $next_key++ ) - return( false ); +function setDeviceStatusX10( $key, $status ) { + $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 ); + if ( $socket < 0 ) { + Fatal( "socket_create() failed: ".socket_strerror($socket) ); + } + $sock_file = ZM_PATH_SOCKS.'/zmx10.sock'; + if ( @socket_connect( $socket, $sock_file ) ) { + $command = "$status;$key"; + if ( !socket_write( $socket, $command ) ) { + Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) ); } - return( true ); + socket_shutdown( $socket, 1 ); + $x10Response = socket_read( $socket, 256 ); + socket_close( $socket ); + } else { + // Can't connect so use script + $command = ZM_PATH_BIN.'/zmx10.pl --command '.escapeshellarg( $status ); + $command .= ' --unit-code '.escapeshellarg( $key ); + //$command .= " 2>/dev/null >&- <&- >/dev/null"; + $x10Response = exec( $command ); + } + if ( preg_match( '/^'.$key.'\s+(.*)/', $x10Response, $matches ) ) + $status = $matches[1]; + else + $status = "unknown"; + return( $status ); } -function checkJsonError($value) -{ - if ( function_exists('json_last_error') ) - { - $value = var_export($value,true); - switch( json_last_error() ) - { - case JSON_ERROR_DEPTH : - Fatal( "Unable to decode JSON string '$value', maximum stack depth exceeded" ); - case JSON_ERROR_CTRL_CHAR : - Fatal( "Unable to decode JSON string '$value', unexpected control character found" ); - case JSON_ERROR_STATE_MISMATCH : - Fatal( "Unable to decode JSON string '$value', invalid or malformed JSON" ); - case JSON_ERROR_SYNTAX : - Fatal( "Unable to decode JSON string '$value', syntax error" ); - default : - Fatal( "Unable to decode JSON string '$value', unexpected error ".json_last_error() ); - case JSON_ERROR_NONE: - break; - } +function logState() { + $state = 'ok'; + + $levelCounts = array( + Logger::FATAL => array( ZM_LOG_ALERT_FAT_COUNT, ZM_LOG_ALARM_FAT_COUNT ), + Logger::ERROR => array( ZM_LOG_ALERT_ERR_COUNT, ZM_LOG_ALARM_ERR_COUNT ), + Logger::WARNING => array( ZM_LOG_ALERT_WAR_COUNT, ZM_LOG_ALARM_WAR_COUNT ), + ); + + $sql = "select Level, count(Level) as LevelCount from Logs where Level < ".Logger::INFO." and TimeKey > unix_timestamp(now() - interval ".ZM_LOG_CHECK_PERIOD." second) group by Level order by Level asc"; + $counts = dbFetchAll( $sql ); + + foreach ( $counts as $count ) { + if ( $count['Level'] <= Logger::PANIC ) + $count['Level'] = Logger::FATAL; + if ( !($levelCount = $levelCounts[$count['Level']]) ) { + Error( "Unexpected Log level ".$count['Level'] ); + next; } + if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) { + $state = 'alarm'; + break; + } elseif ( $levelCount[0] && $count['LevelCount'] >= $levelCount[0] ) { + $state = 'alert'; + } + } + return( $state ); } -function jsonEncode( &$value ) -{ - if ( function_exists('json_encode') ) - { - $string = json_encode( $value ); - checkJsonError($value); - return( $string ); - } - - switch ( gettype($value) ) - { - case 'double': - case 'integer': - return( $value ); - case 'boolean': - return( $value?'true':'false' ); - case 'string': - return( '"'.preg_replace( "/\r?\n/", '\\n', addcslashes($value,'"\\/') ).'"' ); - case 'NULL': - return( 'null' ); - case 'object': - return( '"Object '.addcslashes(get_class($value),'"\\/').'"' ); - case 'array': - if ( isVector( $value ) ) - return( '['.join( ',', array_map( 'jsonEncode', $value) ).']' ); - else - { - $result = '{'; - foreach ($value as $subkey => $subvalue ) - { - if ( $result != '{' ) - $result .= ','; - $result .= '"'.$subkey.'":'.jsonEncode( $subvalue ); - } - return( $result.'}' ); - } - default: - return( '"'.addcslashes(gettype($value),'"\\/').'"' ); - } +function isVector ( &$array ) { + $next_key = 0; + foreach ( array_keys($array) as $key ) { + if ( !is_int( $key ) ) + return( false ); + if ( $key != $next_key++ ) + return( false ); + } + return( true ); } -function jsonDecode( $value ) -{ - if ( function_exists('json_decode') ) - { - $object = json_decode( $value, true ); - checkJsonError($value); - return( $object ); +function checkJsonError($value) { + if ( function_exists('json_last_error') ) { + $value = var_export($value,true); + switch( json_last_error() ) { + case JSON_ERROR_DEPTH : + Fatal( "Unable to decode JSON string '$value', maximum stack depth exceeded" ); + case JSON_ERROR_CTRL_CHAR : + Fatal( "Unable to decode JSON string '$value', unexpected control character found" ); + case JSON_ERROR_STATE_MISMATCH : + Fatal( "Unable to decode JSON string '$value', invalid or malformed JSON" ); + case JSON_ERROR_SYNTAX : + Fatal( "Unable to decode JSON string '$value', syntax error" ); + default : + Fatal( "Unable to decode JSON string '$value', unexpected error ".json_last_error() ); + case JSON_ERROR_NONE: + break; } + } +} - $comment = false; - $unescape = false; - $out = '$result='; - for ( $i = 0; $i < strlen($value); $i++ ) - { - if ( !$comment ) - { - if ( ($value[$i] == '{') || ($value[$i] == '[') ) - $out .= ' array('; - else if ( ($value[$i] == '}') || ($value[$i] == ']') ) - $out .= ')'; - else if ( $value[$i] == ':' ) - $out .= '=>'; - else - $out .= $value[$i]; +function jsonEncode( &$value ) { + if ( function_exists('json_encode') ) { + $string = json_encode( $value ); + checkJsonError($value); + return( $string ); + } + + switch ( gettype($value) ) { + case 'double': + case 'integer': + return( $value ); + case 'boolean': + return( $value?'true':'false' ); + case 'string': + return( '"'.preg_replace( "/\r?\n/", '\\n', addcslashes($value,'"\\/') ).'"' ); + case 'NULL': + return( 'null' ); + case 'object': + return( '"Object '.addcslashes(get_class($value),'"\\/').'"' ); + case 'array': + if ( isVector( $value ) ) + return( '['.join( ',', array_map( 'jsonEncode', $value) ).']' ); + else { + $result = '{'; + foreach ($value as $subkey => $subvalue ) { + if ( $result != '{' ) + $result .= ','; + $result .= '"'.$subkey.'":'.jsonEncode( $subvalue ); } - else if ( !$unescape ) - { - if ( $value[$i] == '\\' ) - $unescape = true; - else - $out .= $value[$i]; - } - else - { - if ( $value[$i] != '/' ) - $out .= '\\'; - $out .= $value[$i]; - $unescape = false; - } - if ( $value[$i] == '"' ) - $comment = !$comment; + return( $result.'}' ); + } + default: + return( '"'.addcslashes(gettype($value),'"\\/').'"' ); + } +} + +function jsonDecode( $value ) { + if ( function_exists('json_decode') ) { + $object = json_decode( $value, true ); + checkJsonError($value); + return( $object ); + } + + $comment = false; + $unescape = false; + $out = '$result='; + for ( $i = 0; $i < strlen($value); $i++ ) { + if ( !$comment ) { + if ( ($value[$i] == '{') || ($value[$i] == '[') ) { + $out .= ' array('; + } else if ( ($value[$i] == '}') || ($value[$i] == ']') ) { + $out .= ')'; + } else if ( $value[$i] == ':' ) { + $out .= '=>'; + } else { + $out .= $value[$i]; + } + } else if ( !$unescape ) { + if ( $value[$i] == '\\' ) + $unescape = true; + else + $out .= $value[$i]; + } else { + if ( $value[$i] != '/' ) + $out .= '\\'; + $out .= $value[$i]; + $unescape = false; } - eval( $out.';' ); - return( $result ); + if ( $value[$i] == '"' ) { + $comment = !$comment; + } + } + eval( $out.';' ); + return( $result ); } define( 'HTTP_STATUS_OK', 200 ); define( 'HTTP_STATUS_BAD_REQUEST', 400 ); define( 'HTTP_STATUS_FORBIDDEN', 403 ); -function ajaxError( $message, $code=HTTP_STATUS_OK ) -{ - Error( $message ); - if ( function_exists( 'ajaxCleanup' ) ) - ajaxCleanup(); - if ( $code == HTTP_STATUS_OK ) - { - $response = array( 'result'=>'Error', 'message'=>$message ); - header( "Content-type: text/plain" ); - exit( jsonEncode( $response ) ); - } - header( "HTTP/1.0 $code $message" ); - exit(); -} - -function ajaxResponse( $result=false ) -{ - if ( function_exists( 'ajaxCleanup' ) ) - ajaxCleanup(); - $response = array( 'result'=>'Ok' ); - if ( is_array( $result ) ) - $response = array_merge( $response, $result ); - elseif ( !empty($result) ) - $response['message'] = $result; +function ajaxError( $message, $code=HTTP_STATUS_OK ) { + Error( $message ); + if ( function_exists( 'ajaxCleanup' ) ) + ajaxCleanup(); + if ( $code == HTTP_STATUS_OK ) { + $response = array( 'result'=>'Error', 'message'=>$message ); header( "Content-type: text/plain" ); exit( jsonEncode( $response ) ); + } + header( "HTTP/1.0 $code $message" ); + exit(); } -function generateConnKey() -{ - return( rand( 1, 999999 ) ); +function ajaxResponse( $result=false ) { + if ( function_exists( 'ajaxCleanup' ) ) + ajaxCleanup(); + $response = array( 'result'=>'Ok' ); + if ( is_array( $result ) ) + $response = array_merge( $response, $result ); + elseif ( !empty($result) ) + $response['message'] = $result; + header( "Content-type: text/plain" ); + exit( jsonEncode( $response ) ); } -function detaintPath( $path ) -{ - // Remove any absolute paths, or relative ones that want to go up - $path = preg_replace( '/\.(?:\.+[\\/][\\/]*)+/', '', $path ); - $path = preg_replace( '/^[\\/]+/', '', $path ); - return( $path ); +function generateConnKey() { + return( rand( 1, 999999 ) ); } -function getSkinFile( $file ) -{ - global $skinBase; - $skinFile = false; - foreach ( $skinBase as $skin ) - { - $tempSkinFile = detaintPath( 'skins'.'/'.$skin.'/'.$file ); - if ( file_exists( $tempSkinFile ) ) - $skinFile = $tempSkinFile; - } - return( $skinFile ); +function detaintPath( $path ) { + // Remove any absolute paths, or relative ones that want to go up + $path = preg_replace( '/\.(?:\.+[\\/][\\/]*)+/', '', $path ); + $path = preg_replace( '/^[\\/]+/', '', $path ); + return( $path ); +} + +function getSkinFile( $file ) { + global $skinBase; + $skinFile = false; + foreach ( $skinBase as $skin ) { + $tempSkinFile = detaintPath( 'skins'.'/'.$skin.'/'.$file ); + if ( file_exists( $tempSkinFile ) ) + $skinFile = $tempSkinFile; + } + return( $skinFile ); } function getSkinIncludes( $file, $includeBase=false, $asOverride=false ) { - global $skinBase; - $skinFile = false; - foreach ( $skinBase as $skin ) - { - $tempSkinFile = detaintPath( 'skins'.'/'.$skin.'/'.$file ); - if ( file_exists( $tempSkinFile ) ) - $skinFile = $tempSkinFile; - } - $includeFiles = array(); - if ( $asOverride ) - { - if ( $skinFile ) - $includeFiles[] = $skinFile; - else if ( $includeBase ) - $includeFiles[] = $file; - } - else - { - if ( $includeBase ) - $includeFiles[] = $file; - if ( $skinFile ) - $includeFiles[] = $skinFile; - } - return( $includeFiles ); + global $skinBase; + $skinFile = false; + foreach ( $skinBase as $skin ) { + $tempSkinFile = detaintPath( 'skins'.'/'.$skin.'/'.$file ); + if ( file_exists( $tempSkinFile ) ) + $skinFile = $tempSkinFile; + } + $includeFiles = array(); + if ( $asOverride ) { + if ( $skinFile ) + $includeFiles[] = $skinFile; + else if ( $includeBase ) + $includeFiles[] = $file; + } else { + if ( $includeBase ) + $includeFiles[] = $file; + if ( $skinFile ) + $includeFiles[] = $skinFile; + } + return( $includeFiles ); } -function requestVar( $name, $default="" ) -{ - return( isset($_REQUEST[$name])?validHtmlStr($_REQUEST[$name]):$default ); +function requestVar( $name, $default="" ) { + return( isset($_REQUEST[$name])?validHtmlStr($_REQUEST[$name]):$default ); } // For numbers etc in javascript or tags etc -function validInt( $input ) -{ - return( preg_replace( '/\D/', '', $input ) ); +function validInt( $input ) { + return( preg_replace( '/\D/', '', $input ) ); } -function validNum( $input ) -{ - return( preg_replace( '/[^\d.-]/', '', $input ) ); +function validNum( $input ) { + return( preg_replace( '/[^\d.-]/', '', $input ) ); } // For general strings -function validStr( $input ) -{ - return( strip_tags( $input ) ); +function validStr( $input ) { + return( strip_tags( $input ) ); } // For strings in javascript or tags etc, expected to be in quotes so further quotes escaped rather than converted -function validJsStr( $input ) -{ - return( strip_tags( addslashes( $input ) ) ); +function validJsStr( $input ) { + return( strip_tags( addslashes( $input ) ) ); } // For general text in pages outside of tags or quotes so quotes converted to entities -function validHtmlStr( $input ) -{ - return( htmlspecialchars( $input, ENT_QUOTES ) ); +function validHtmlStr( $input ) { + return( htmlspecialchars( $input, ENT_QUOTES ) ); } function getStreamHTML( $monitor, $scale=100 ) { diff --git a/web/skins/classic/css/classic/views/event.css b/web/skins/classic/css/classic/views/event.css index 995a06c1d..13ac0cc0b 100644 --- a/web/skins/classic/css/classic/views/event.css +++ b/web/skins/classic/css/classic/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,16 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} + #imageFeed { text-align: center; } diff --git a/web/skins/classic/css/dark/views/event.css b/web/skins/classic/css/dark/views/event.css index 995a06c1d..13ac0cc0b 100644 --- a/web/skins/classic/css/dark/views/event.css +++ b/web/skins/classic/css/dark/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,16 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} + #imageFeed { text-align: center; } diff --git a/web/skins/classic/css/flat/views/event.css b/web/skins/classic/css/flat/views/event.css index 17c4f70cf..e69fe14f6 100644 --- a/web/skins/classic/css/flat/views/event.css +++ b/web/skins/classic/css/flat/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,15 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} #imageFeed { text-align: center; } diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index 1367bc8b1..a6c459760 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -1,10 +1,11 @@ var requestQueue = new Request.Queue( { concurrent: 2 } ); -function Monitor( index, id, connKey ) +function Monitor( index, monitorData ) { this.index = index; - this.id = id; - this.connKey = connKey; + this.id = monitorData.id; + this.connKey = monitorData.connKey; + this.server_url = monitorData.server_url; this.status = null; this.alarmState = STATE_IDLE; this.lastAlarmState = STATE_IDLE; @@ -110,7 +111,7 @@ function Monitor( index, id, connKey ) this.streamCmdReq.send( this.streamCmdParms+"&command="+CMD_QUERY ); } - this.streamCmdReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, onSuccess: this.getStreamCmdResponse.bind( this ), onTimeout: this.streamCmdQuery.bind( this, true ), link: 'cancel' } ); + this.streamCmdReq = new Request.JSON( { url: this.server_url, method: 'get', timeout: AJAX_TIMEOUT, onSuccess: this.getStreamCmdResponse.bind( this ), onTimeout: this.streamCmdQuery.bind( this, true ), link: 'cancel' } ); requestQueue.addRequest( "cmdReq"+this.id, this.streamCmdReq ); } @@ -146,7 +147,7 @@ function initPage() { for ( var i = 0; i < monitorData.length; i++ ) { - monitors[i] = new Monitor( i, monitorData[i].id, monitorData[i].connKey ); + monitors[i] = new Monitor( i, monitorData[i] ); var delay = Math.round( (Math.random()+0.5)*statusRefreshTimeout ); monitors[i].start( delay ); } diff --git a/web/skins/classic/views/js/montage.js.php b/web/skins/classic/views/js/montage.js.php index 80f652fd5..7eaebb75b 100644 --- a/web/skins/classic/views/js/montage.js.php +++ b/web/skins/classic/views/js/montage.js.php @@ -35,7 +35,8 @@ monitorData[monitorData.length] = { 'id': Id() ?>, 'connKey': connKey() ?>, 'width': Width() ?>, - 'height':Height() ?> + 'height':Height() ?>, + 'server_url': 'Server()->Url().$_SERVER['PHP_SELF'] ?>' };

-
+
- +