Merge branch 'master' into fix_zone_edit

This commit is contained in:
Isaac Connor 2016-05-24 15:30:56 -04:00
commit 89f58daf89
38 changed files with 2749 additions and 2193 deletions

View File

@ -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

View File

@ -5,17 +5,23 @@ Maintainer: Dmitry Smirnov <onlyjob@debian.org>
Uploaders: Vagrant Cascadian <vagrant@debian.org>
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

View File

@ -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

View File

@ -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
^^^^^^^^^^^^^^^^^^^

View File

@ -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() {

View File

@ -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<Action>);
my %MessageID_of :ATTR(:get<MessageID>);
my %ReplyTo_of :ATTR(:get<ReplyTo>);
my %To_of :ATTR(:get<To>);
__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;

View File

@ -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 => {

View File

@ -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__',
};
;

View File

@ -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<Attribs>);
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;

View File

@ -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";

View File

@ -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

View File

@ -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",

View File

@ -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;

View File

@ -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();

View File

@ -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
{

View File

@ -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!)

View File

@ -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()

View File

@ -1,5 +1,4 @@
<?php
define( "MSG_TIMEOUT", 2.0 );
define( "MSG_DATA_SIZE", 4+256 );
@ -35,8 +34,7 @@ if ( canEdit( 'Monitors' ) )
}
}
ajaxResponse( exec( escapeshellcmd( $zmuCommand ) ) );
} else {
ajaxError( 'Insufficient permissions' );
}
ajaxError( 'Unrecognised action or insufficient permissions' );
?>

View File

@ -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(

View File

@ -0,0 +1,155 @@
<?php
App::uses('AppController', 'Controller');
/**
* Servers Controller
*
* @property Server $Server
* @property PaginatorComponent $Paginator
*/
class ServersController extends AppController {
/**
* Components
*
* @var array
*/
public $components = array('Paginator', 'RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
$canView = $this->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'));
}
}
}

View File

@ -0,0 +1,74 @@
<?php
App::uses('AppModel', 'Model');
/**
* Server Model
*
* @property Event $Event
* @property Zone $Zone
*/
class Server extends AppModel {
/**
* Use table
*
* @var mixed False or table name
*/
public $useTable = 'Servers';
/**
* Primary key field
*
* @var string
*/
public $primaryKey = 'Id';
/**
* Display field
*
* @var string
*/
public $displayField = 'Name';
public $recursive = -1;
/**
* Validation rules
*
* @var array
*/
public $validate = array(
'Id' => 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' => ''
)
);
}

View File

@ -0,0 +1,2 @@
echo json_encode($message);
echo json_encode($server);

View File

@ -0,0 +1 @@
echo json_encode($servers);

View File

@ -0,0 +1 @@
echo json_encode($server);

View File

@ -0,0 +1,2 @@
$xml = Xml::fromArray(array('response' => $message));
echo $xml->asXML();

View File

@ -0,0 +1,2 @@
$xml = Xml::fromArray(array('response' => $monitors));
echo $xml->asXML();

View File

@ -0,0 +1,2 @@
$xml = Xml::fromArray(array('response' => $monitor));
echo $xml->asXML();

152
web/includes/Event.php Normal file
View File

@ -0,0 +1,152 @@
<?php
require_once( 'database.php' );
require_once( 'Storage.php' );
class Event {
public function __construct( $IdOrRow ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT *,unix_timestamp(StartTime) as Time FROM Events WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Event record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Event Constructor ($IdOrRow)");
return;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $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='&amp;' ) {
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
?>

103
web/includes/Frame.php Normal file
View File

@ -0,0 +1,103 @@
<?php
require_once( 'database.php' );
require_once( 'Event.php' );
class Frame {
public function __construct( $IdOrRow ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Frames WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Frame record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Frame Constructor ($IdOrRow)");
return;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $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
?>

View File

@ -1,28 +1,28 @@
<?php
require_once( 'database.php' );
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'} = '';
}
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];
}
}
?>

51
web/includes/Storage.php Normal file
View File

@ -0,0 +1,51 @@
<?php
require_once( 'database.php' );
class Storage {
public function __construct( $IdOrRow = NULL ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Storage WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Storage record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
}
}
if ( $row ) {
foreach ($row as $k => $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;
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 );
}

View File

@ -35,7 +35,8 @@ monitorData[monitorData.length] = {
'id': <?php echo $monitor->Id() ?>,
'connKey': <?php echo $monitor->connKey() ?>,
'width': <?php echo $monitor->Width() ?>,
'height':<?php echo $monitor->Height() ?>
'height':<?php echo $monitor->Height() ?>,
'server_url': '<?php echo $monitor->Server()->Url().$_SERVER['PHP_SELF'] ?>'
};
<?php
}

View File

@ -47,9 +47,9 @@ xhtmlHeaders(__FILE__, translate('Zones') );
<div id="headerButtons"><a href="#" onclick="closeWindow();"><?php echo translate('Close') ?></a></div>
<h2><?php echo translate('Zones') ?></h2>
</div>
<div id="content">
<div id="content" style="width:<?php echo $monitor->Width() ?>px; height:<?php echo $monitor->Height() ?>px; position:relative; margin: 0 auto;">
<?php echo getStreamHTML( $monitor ); ?>
<svg class="zones" width="<?php echo $monitor->Width ?>" height="<?php echo $monitor->Height ?>" style="margin-top: -<?php echo $monitor->Height ?>px;background: none;">
<svg class="zones" width="<?php echo $monitor->Width() ?>" height="<?php echo $monitor->Height() ?>" style="position:absolute; top: 0; left: 0; background: none;">
<?php
foreach( array_reverse($zones) as $zone ) {
?>