Merge branch 'master' into feature-h264-videostorage
This commit is contained in:
commit
26bba58c56
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (zoneminder)
|
||||
set(zoneminder_VERSION "1.29.2")
|
||||
file (STRINGS "version" zoneminder_VERSION)
|
||||
# make API version a minor of ZM version
|
||||
set(zoneminder_API_VERSION "${zoneminder_VERSION}.1")
|
||||
|
||||
|
|
|
@ -373,7 +373,7 @@ UPDATE States SET IsActive = '1' WHERE Name = 'default';
|
|||
-- If duplicate states existed while upgrading, that is
|
||||
-- very likely an error that ZM allowed earlier, so
|
||||
-- we are picking up the first one and deleting the others
|
||||
ALTER IGNORE TABLE States ADD UNIQUE (Name);
|
||||
ALTER TABLE States ADD UNIQUE (Name);
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
--
|
||||
-- This updates a 1.29.1 database to 1.30.0
|
||||
--
|
||||
-- No changes required
|
||||
--
|
|
@ -1,7 +1,6 @@
|
|||
Alias /zm /usr/share/zoneminder/www
|
||||
|
||||
<Directory /usr/share/zoneminder/www>
|
||||
php_flag register_globals off
|
||||
Options Indexes FollowSymLinks
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.php
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -49,10 +49,9 @@ New installs
|
|||
Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous
|
||||
step.
|
||||
|
||||
Additionally, you must also edit
|
||||
/usr/share/zoneminder/www/api/app/Config/database.php in a similar manner.
|
||||
Scroll down and change login and password to the values you created in the
|
||||
previous step.
|
||||
This version of zoneminder no longer requires you to make a similar change
|
||||
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
|
||||
This now happens dynamically. Do *not* make any changes to this file.
|
||||
|
||||
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
|
||||
timezone. PHP will complain loudly if this is not set, or if it is set
|
||||
|
@ -113,10 +112,9 @@ Upgrades
|
|||
Compare /etc/zm/zm.conf to /etc/zm/zm.conf.rpmnew. Verify that zm.conf
|
||||
contains any new config settings that may be in zm.conf.rpmnew.
|
||||
|
||||
Additionally, you must also edit
|
||||
/usr/share/zoneminder/www/api/app/Config/database.php in a similar manner.
|
||||
Scroll down and change login and password to the values you used
|
||||
previsouly.
|
||||
This version of zoneminder no longer requires you to make a similar change
|
||||
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
|
||||
This now happens dynamically. Do *not* make any changes to this file.
|
||||
|
||||
2. Verify permissions of the zmuser account.
|
||||
|
||||
|
|
|
@ -40,11 +40,6 @@ New installs
|
|||
other than zmuser/zmpass then you must now edit /etc/zm.conf. Change
|
||||
ZM_DB_USER and ZM_DB_PASS to the values you created in the previous step.
|
||||
|
||||
Additionally, you must also edit
|
||||
/usr/share/zoneminder/www/api/app/Config/database.php in a similar manner.
|
||||
Scroll down and change login and password to the values you created in the
|
||||
previous step.
|
||||
|
||||
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
|
||||
timezone. PHP will complain loudly if this is not set, or if it is set
|
||||
incorrectly, and these complaints will show up in the zoneminder logging
|
||||
|
@ -89,9 +84,8 @@ New installs
|
|||
|
||||
Then point your web browser to http://<machine name or ip>/zm
|
||||
|
||||
================================================================================
|
||||
UPGRADES
|
||||
================================================================================
|
||||
Upgrades
|
||||
========
|
||||
|
||||
1. Verify /etc/zm.conf.
|
||||
|
||||
|
@ -105,11 +99,6 @@ New installs
|
|||
Compare /etc/zm.conf to /etc/zm.conf.rpmnew. Verify that zm.conf
|
||||
contains any new config settings that may be in zm.conf.rpmnew.
|
||||
|
||||
Additionally, you must also edit
|
||||
/usr/share/zoneminder/www/api/app/Config/database.php in a similar manner.
|
||||
Scroll down and change login and password to the values you used
|
||||
previsouly.
|
||||
|
||||
2. Verify permissions of the zmuser account.
|
||||
|
||||
Over time, the database account permissions required for normal operation
|
||||
|
|
|
@ -47,10 +47,9 @@ New installs
|
|||
Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous
|
||||
step.
|
||||
|
||||
Additionally, you must also edit
|
||||
/usr/share/zoneminder/www/api/app/Config/database.php in a similar manner.
|
||||
Scroll down and change login and password to the values you created in the
|
||||
previous step.
|
||||
This version of zoneminder no longer requires you to make a similar change
|
||||
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
|
||||
This now happens dynamically. Do *not* make any changes to this file.
|
||||
|
||||
4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local
|
||||
timezone. PHP will complain loudly if this is not set, or if it is set
|
||||
|
@ -111,10 +110,9 @@ Upgrades
|
|||
Compare /etc/zm/zm.conf to /etc/zm/zm.conf.rpmnew. Verify that zm.conf
|
||||
contains any new config settings that may be in zm.conf.rpmnew.
|
||||
|
||||
Additionally, you must also edit
|
||||
/usr/share/zoneminder/www/api/app/Config/database.php in a similar manner.
|
||||
Scroll down and change login and password to the values you used
|
||||
previsouly.
|
||||
This version of zoneminder no longer requires you to make a similar change
|
||||
to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
|
||||
This now happens dynamically. Do *not* make any changes to this file.
|
||||
|
||||
2. Verify permissions of the zmuser account.
|
||||
|
||||
|
|
|
@ -16,6 +16,12 @@ Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh
|
|||
,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
|
||||
|
@ -45,6 +51,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libsys-mmap-perl [!hurd-any]
|
||||
,liburi-encode-perl
|
||||
,libwww-perl
|
||||
,libdata-uuid-perl
|
||||
,mysql-client | virtual-mysql-client
|
||||
,perl-modules
|
||||
,php5-mysql, php5-gd
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
Alias /zm /usr/share/zoneminder/www
|
||||
|
||||
<Directory /usr/share/zoneminder/www>
|
||||
php_flag register_globals off
|
||||
Options Indexes FollowSymLinks
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.php
|
||||
|
|
|
@ -1,9 +1,43 @@
|
|||
zoneminder (1.28.1+1-vivid-SNAPSHOT2015081701) vivid; urgency=medium
|
||||
zoneminder (1.29.0+dfsg-1) unstable; urgency=low
|
||||
|
||||
* include api, switch to cmake build
|
||||
* New upstream release [February 2016] (Closes: #788317, #770851).
|
||||
|
||||
-- Isaac Connor <iconnor@connortechnology.com> Mon, 17 Aug 2015 10:29:23 -0400
|
||||
[ Dmitry Smirnov <onlyjob@debian.org> ]
|
||||
* copyright/Files-Excluded += "onvif/*" due to licensing uncertainty.
|
||||
* Fixed FTBFS when built with dpkg-buildpackage -A (Closes: #806126).
|
||||
* FFmpeg 2.9 support. Thanks, Andreas Cadhalpun. (Closes: #803850).
|
||||
* Use "ffmpeg" instead of "avconv":
|
||||
+ "libav_path.patch" replaced with "default_ffmpeg_path.patch".
|
||||
* zoneminder/Depends:
|
||||
- perl-modules (package-relation-with-perl-modules)
|
||||
- libav-tools
|
||||
* zoneminder/Recommends:
|
||||
+ ffmpeg | libav-tools
|
||||
* Updated Vcs URLs.
|
||||
* Build/install new man pages.
|
||||
* Removed obsolete lintian-overrides.
|
||||
* README: grant "index" right to DB user.
|
||||
* systemd: start after MySQL but do not require the latter.
|
||||
* Added new patch with spelling corrections.
|
||||
* Removed obsolete patches:
|
||||
- 783.patch
|
||||
- 980-fix-image-size.patch
|
||||
- cmake-fix-confpath.patch
|
||||
- cmake.patch
|
||||
- cmake-gnutls.patch
|
||||
- fix-html-export.patch
|
||||
- format-hardening.patch
|
||||
- libv4l1-videodev.h.patch
|
||||
- pod_man_fixes.patch
|
||||
- pod_name_fixes.patch
|
||||
- pod_zmupdate-to-pod2usage.patch
|
||||
- respect-privacy.patch
|
||||
- zmtrigger-plus.patch
|
||||
|
||||
[ Vagrant Cascadian <vagrant@debian.org> ]
|
||||
* Remove myself from Uploaders.
|
||||
|
||||
-- Dmitry Smirnov <onlyjob@debian.org> Tue, 09 Feb 2016 15:40:32 +1100
|
||||
|
||||
zoneminder (1.28.1-8) unstable; urgency=medium
|
||||
|
|
@ -8,7 +8,6 @@ ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
|
|||
|
||||
Alias /zm /usr/share/zoneminder/www
|
||||
<Directory /usr/share/zoneminder/www>
|
||||
php_flag register_globals off
|
||||
Options Indexes FollowSymLinks
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.php
|
|
@ -5,7 +5,11 @@ Maintainer: Dmitry Smirnov <onlyjob@debian.org>
|
|||
Uploaders: Vagrant Cascadian <vagrant@debian.org>
|
||||
Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree
|
||||
,cmake
|
||||
,libavcodec-ffmpeg-dev, libavformat-ffmpeg-dev, libswscale-ffmpeg-dev, libavutil-ffmpeg-dev, libavdevice-ffmpeg-dev
|
||||
,libavdevice-dev (>= 6:10~)
|
||||
,libavcodec-dev (>= 6:10~)
|
||||
,libavformat-dev (>= 6:10~)
|
||||
,libavutil-dev (>= 6:10~)
|
||||
,libswscale-dev (>= 6:10~)
|
||||
,libbz2-dev
|
||||
,libgcrypt-dev
|
||||
,libcurl4-gnutls-dev
|
||||
|
@ -21,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
|
||||
|
@ -55,16 +60,18 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,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, php5-gd
|
||||
,php5-mysql | php-mysql, php5-gd | php-gd
|
||||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
,zip
|
||||
Recommends: ${misc:Recommends}
|
||||
,libapache2-mod-php5 | php5-fpm
|
||||
,libapache2-mod-php5 | libapache2-mod-php | php5-fpm | php-fpm
|
||||
,mysql-server | virtual-mysql-server
|
||||
,zoneminder-doc (>= ${source:Version})
|
||||
,ffmpeg
|
||||
Suggests: fcgiwrap, logrotate
|
||||
Description: video camera security and surveillance solution
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
42
docs/api.rst
42
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
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -61,7 +61,7 @@ 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',
|
||||
|
@ -69,8 +69,11 @@ sub send_multi() {
|
|||
|
||||
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() {
|
||||
|
|
|
@ -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;
|
|
@ -34,6 +34,10 @@ sub ProbeOp {
|
|||
|
||||
},
|
||||
header => {
|
||||
'use' => 'literal',
|
||||
namespace => 'http://schemas.xmlsoap.org/ws/2004/08/addressing',
|
||||
encodingStyle => '',
|
||||
parts => [qw( WSDiscovery10::Elements::Header )],
|
||||
|
||||
},
|
||||
headerfault => {
|
||||
|
|
|
@ -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__',
|
||||
};
|
||||
;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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,7 +102,6 @@ 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=?' );
|
||||
|
@ -109,9 +114,124 @@ BEGIN
|
|||
my $result = $sth->fetchrow_hashref();
|
||||
$Config{ZM_SERVER_ID} = $$result{Id};
|
||||
}
|
||||
$sth->finish();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
__END__
|
||||
|
||||
|
@ -121,7 +241,7 @@ ZoneMinder::Config - ZoneMinder configuration module.
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ZoneMinder::Config qw(:all);
|
||||
use ZoneMinder::Config qw(:all);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
@ -136,7 +256,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 +297,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
|
||||
|
|
|
@ -1,276 +0,0 @@
|
|||
# ==========================================================================
|
||||
#
|
||||
# ZoneMinder Config Admin Module, $Date$, $Revision$
|
||||
# Copyright (C) 2001-2008 Philip Coombes
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ==========================================================================
|
||||
#
|
||||
# This module contains the debug definitions and functions used by the rest
|
||||
# of the ZoneMinder scripts
|
||||
#
|
||||
package ZoneMinder::ConfigAdmin;
|
||||
|
||||
use 5.006;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
require Exporter;
|
||||
require ZoneMinder::Base;
|
||||
|
||||
our @ISA = qw(Exporter ZoneMinder::Base);
|
||||
|
||||
# Items to export into callers namespace by default. Note: do not export
|
||||
# names by default without a very good reason. Use EXPORT_OK instead.
|
||||
# Do not simply export all your public functions/methods/constants.
|
||||
|
||||
# This allows declaration use ZoneMinder ':all';
|
||||
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
|
||||
# will save memory.
|
||||
our %EXPORT_TAGS = (
|
||||
'functions' => [ qw(
|
||||
loadConfigFromDB
|
||||
saveConfigToDB
|
||||
) ]
|
||||
);
|
||||
push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS;
|
||||
|
||||
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'functions'} } );
|
||||
|
||||
our @EXPORT = qw();
|
||||
|
||||
our $VERSION = $ZoneMinder::Base::VERSION;
|
||||
|
||||
# ==========================================================================
|
||||
#
|
||||
# Configuration Administration
|
||||
#
|
||||
# ==========================================================================
|
||||
|
||||
use ZoneMinder::Config qw(:all);
|
||||
use ZoneMinder::ConfigData qw(:all);
|
||||
|
||||
use Carp;
|
||||
|
||||
sub loadConfigFromDB
|
||||
{
|
||||
print( "Loading config from DB\n" );
|
||||
my $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME}
|
||||
.";host=".$Config{ZM_DB_HOST}
|
||||
,$Config{ZM_DB_USER}
|
||||
,$Config{ZM_DB_PASS}
|
||||
);
|
||||
|
||||
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();
|
||||
$dbh->disconnect();
|
||||
return( $option_count );
|
||||
}
|
||||
|
||||
sub saveConfigToDB
|
||||
{
|
||||
print( "Saving config to DB\n" );
|
||||
my $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME}
|
||||
.";host=".$Config{ZM_DB_HOST}
|
||||
,$Config{ZM_DB_USER}
|
||||
,$Config{ZM_DB_PASS}
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
$dbh->disconnect();
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ZoneMinder::ConfigAdmin - ZoneMinder Configuration Administration module
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ZoneMinder::ConfigAdmin;
|
||||
use ZoneMinder::ConfigAdmin qw(:all);
|
||||
|
||||
loadConfigFromDB();
|
||||
saveConfigToDB();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The ZoneMinder:ConfigAdmin module contains the master definition of the
|
||||
ZoneMinder configuration options as well as helper methods. This module is
|
||||
intended for specialist confguration management and would not normally be
|
||||
used by end users.
|
||||
|
||||
The configuration held in this module, which was previously in zmconfig.pl,
|
||||
includes the name, default value, description, help text, type and category
|
||||
for each option, as well as a number of additional fields in a small number
|
||||
of cases.
|
||||
|
||||
=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.
|
||||
|
||||
=back
|
||||
|
||||
=head2 EXPORT
|
||||
|
||||
None by default.
|
||||
The :data tag will export the various configuration data structures
|
||||
The :functions tag will export the helper functions.
|
||||
The :all tag will export all above symbols.
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
http://www.zoneminder.com
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
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.
|
||||
|
||||
|
||||
=cut
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
@ -258,7 +262,7 @@ sub run
|
|||
killAll( 1 );
|
||||
|
||||
socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" );
|
||||
unlink( main::SOCK_FILE ) or Error( "Unable to unlink " . main::SOCK_FILE );
|
||||
unlink( main::SOCK_FILE ) or Error( "Unable to unlink " . main::SOCK_FILE .". Error message was: $!" ) if ( -e main::SOCK_FILE );
|
||||
bind( SERVER, $saddr ) or Fatal( "Can't bind to " . main::SOCK_FILE . ": $!" );
|
||||
listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" );
|
||||
|
||||
|
@ -370,8 +374,8 @@ sub run
|
|||
.strftime( '%y/%m/%d %H:%M:%S', localtime() )
|
||||
."\n"
|
||||
);
|
||||
unlink( main::SOCK_FILE );
|
||||
unlink( ZM_PID );
|
||||
unlink( main::SOCK_FILE ) or Error( "Unable to unlink " . main::SOCK_FILE .". Error message was: $!" ) if ( -e main::SOCK_FILE );
|
||||
unlink( ZM_PID ) or Error( "Unable to unlink " . ZM_PID .". Error message was: $!" ) if ( -e ZM_PID );
|
||||
exit();
|
||||
}
|
||||
|
||||
|
@ -756,8 +760,8 @@ sub shutdownAll
|
|||
.strftime( '%y/%m/%d %H:%M:%S', localtime() )
|
||||
."\n"
|
||||
);
|
||||
unlink( main::SOCK_FILE );
|
||||
unlink( ZM_PID );
|
||||
unlink( main::SOCK_FILE ) or Error( "Unable to unlink " . main::SOCK_FILE .". Error message was: $!" ) if ( -e main::SOCK_FILE );
|
||||
unlink( ZM_PID ) or Error( "Unable to unlink " . ZM_PID .". Error message was: $!" ) if ( -e ZM_PID );
|
||||
close( CLIENT );
|
||||
close( SERVER );
|
||||
exit();
|
||||
|
|
|
@ -226,7 +226,12 @@ if ( $command =~ /^(?:start|restart)$/ )
|
|||
zmMemTidy();
|
||||
runCommand( "zmdc.pl startup" );
|
||||
|
||||
Info( "Starting up services" . ( $Config{ZM_SERVER_ID} ? " for server $Config{ZM_SERVER_ID}\n" : "\n" ) );
|
||||
if ( $Config{ZM_SERVER_ID} ) {
|
||||
Info( "Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n");
|
||||
} else {
|
||||
Info( "Single server configuration detected. Starting up services." );
|
||||
}
|
||||
|
||||
my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors';
|
||||
my $sth = $dbh->prepare_cached( $sql )
|
||||
or Fatal( "Can't prepare '$sql': ".$dbh->errstr() );
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -72,7 +72,6 @@ use ZoneMinder::Config qw(:all);
|
|||
use ZoneMinder::Logger qw(:all);
|
||||
use ZoneMinder::General qw(:all);
|
||||
use ZoneMinder::Database qw(:all);
|
||||
use ZoneMinder::ConfigAdmin qw( :functions );
|
||||
use POSIX;
|
||||
use DBI;
|
||||
use Getopt::Long;
|
||||
|
@ -155,6 +154,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 +184,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 +241,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 +259,7 @@ if ( $zoneFix )
|
|||
$zone->{Id}
|
||||
) or die( "Can't execute: ".$sth->errstr() );
|
||||
}
|
||||
$sth->finish();
|
||||
}
|
||||
if ( $migrateEvents )
|
||||
{
|
||||
|
@ -318,11 +321,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 +339,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
|
||||
|
@ -494,8 +499,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 +1069,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
|
||||
{
|
||||
|
|
162
src/zm_comms.cpp
162
src/zm_comms.cpp
|
@ -35,6 +35,8 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h> // for debug output
|
||||
#include <stdio.h> // for snprintf
|
||||
|
||||
#ifdef SOLARIS
|
||||
#include <sys/filio.h> // define FIONREAD
|
||||
|
@ -516,6 +518,166 @@ bool Socket::setNoDelay( bool nodelay )
|
|||
return( true );
|
||||
}
|
||||
|
||||
bool InetSocket::connect( const char *host, const char *serv )
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp;
|
||||
int s;
|
||||
char buf[255];
|
||||
|
||||
mAddressFamily = AF_UNSPEC;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
||||
hints.ai_socktype = getType();
|
||||
hints.ai_flags = 0;
|
||||
hints.ai_protocol = 0; /* Any protocol */
|
||||
|
||||
s = getaddrinfo(host, serv, &hints, &result);
|
||||
if (s != 0) {
|
||||
Error( "connect(): getaddrinfo: %s", gai_strerror(s) );
|
||||
return( false );
|
||||
}
|
||||
|
||||
/* getaddrinfo() returns a list of address structures.
|
||||
* Try each address until we successfully connect(2).
|
||||
* If socket(2) (or connect(2)) fails, we (close the socket
|
||||
* and) try the next address. */
|
||||
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
if (mSd != -1) {
|
||||
if (::connect(mSd, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||
break; /* Success */
|
||||
continue;
|
||||
}
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
if (rp->ai_family == AF_INET) {
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in *)rp->ai_addr)->sin_addr, buf, sizeof(buf)-1);
|
||||
}
|
||||
else if (rp->ai_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, buf, sizeof(buf)-1);
|
||||
}
|
||||
else {
|
||||
strncpy(buf, "n/a", sizeof(buf)-1);
|
||||
}
|
||||
Debug( 1, "connect(): Trying '%s', family '%d', proto '%d'", buf, rp->ai_family, rp->ai_protocol);
|
||||
mSd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
if (mSd == -1)
|
||||
continue;
|
||||
|
||||
int val = 1;
|
||||
|
||||
(void)::setsockopt( mSd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val) );
|
||||
(void)::setsockopt( mSd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val) );
|
||||
mAddressFamily = rp->ai_family; /* save AF_ for ctrl and data connections */
|
||||
|
||||
if (::connect(mSd, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||
break; /* Success */
|
||||
|
||||
::close(mSd);
|
||||
}
|
||||
|
||||
if (rp == NULL) { /* No address succeeded */
|
||||
Error( "connect(), Could not connect" );
|
||||
mAddressFamily = AF_UNSPEC;
|
||||
return( false );
|
||||
}
|
||||
|
||||
freeaddrinfo(result); /* No longer needed */
|
||||
|
||||
mState = CONNECTED;
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool InetSocket::connect( const char *host, int port )
|
||||
{
|
||||
char serv[8];
|
||||
snprintf(serv, sizeof(serv), "%d", port);
|
||||
|
||||
return connect( host, serv );
|
||||
}
|
||||
|
||||
bool InetSocket::bind( const char * host, const char * serv )
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp;
|
||||
int s;
|
||||
char buf[255];
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
||||
hints.ai_socktype = getType();
|
||||
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
|
||||
hints.ai_protocol = 0; /* Any protocol */
|
||||
hints.ai_canonname = NULL;
|
||||
hints.ai_addr = NULL;
|
||||
hints.ai_next = NULL;
|
||||
|
||||
s = getaddrinfo(host, serv, &hints, &result);
|
||||
if (s != 0) {
|
||||
Error( "bind(): getaddrinfo: %s", gai_strerror(s) );
|
||||
return( false );
|
||||
}
|
||||
|
||||
/* getaddrinfo() returns a list of address structures.
|
||||
* Try each address until we successfully bind(2).
|
||||
* If socket(2) (or bind(2)) fails, we (close the socket
|
||||
* and) try the next address. */
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
if (rp->ai_family == AF_INET) {
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in *)rp->ai_addr)->sin_addr, buf, sizeof(buf)-1);
|
||||
}
|
||||
else if (rp->ai_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, buf, sizeof(buf)-1);
|
||||
}
|
||||
else {
|
||||
strncpy(buf, "n/a", sizeof(buf)-1);
|
||||
}
|
||||
Debug( 1, "bind(): Trying '%s', family '%d', proto '%d'", buf, rp->ai_family, rp->ai_protocol);
|
||||
mSd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
if (mSd == -1)
|
||||
continue;
|
||||
|
||||
mState = DISCONNECTED;
|
||||
if (::bind(mSd, rp->ai_addr, rp->ai_addrlen) == 0)
|
||||
break; /* Success */
|
||||
|
||||
::close(mSd);
|
||||
mSd = -1;
|
||||
}
|
||||
|
||||
if (rp == NULL) { /* No address succeeded */
|
||||
Error( "bind(), Could not bind" );
|
||||
return( false );
|
||||
}
|
||||
|
||||
freeaddrinfo(result); /* No longer needed */
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool InetSocket::bind( const char * serv )
|
||||
{
|
||||
return bind( NULL, serv);
|
||||
}
|
||||
|
||||
bool InetSocket::bind( const char * host, int port )
|
||||
{
|
||||
char serv[8];
|
||||
snprintf(serv, sizeof(serv), "%d", port);
|
||||
|
||||
return bind( host, serv );
|
||||
}
|
||||
|
||||
bool InetSocket::bind( int port )
|
||||
{
|
||||
char serv[8];
|
||||
snprintf(serv, sizeof(serv), "%d", port);
|
||||
|
||||
return bind( NULL, serv );
|
||||
}
|
||||
|
||||
bool TcpInetServer::listen()
|
||||
{
|
||||
return( Socket::listen() );
|
||||
|
|
158
src/zm_comms.h
158
src/zm_comms.h
|
@ -399,103 +399,27 @@ public:
|
|||
|
||||
class InetSocket : virtual public Socket
|
||||
{
|
||||
protected:
|
||||
int mAddressFamily;
|
||||
|
||||
public:
|
||||
int getDomain() const
|
||||
{
|
||||
return( AF_INET );
|
||||
}
|
||||
virtual socklen_t getAddrSize() const
|
||||
{
|
||||
int getDomain() const
|
||||
{
|
||||
return( mAddressFamily );
|
||||
}
|
||||
virtual socklen_t getAddrSize() const
|
||||
{
|
||||
return( SockAddrInet::addrSize() );
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool resolveLocal( const char *host, const char *serv, const char *proto )
|
||||
{
|
||||
SockAddrInet *addr = new SockAddrInet;
|
||||
mLocalAddr = addr;
|
||||
return( addr->resolve( host, serv, proto ) );
|
||||
}
|
||||
bool resolveLocal( const char *host, int port, const char *proto )
|
||||
{
|
||||
SockAddrInet *addr = new SockAddrInet;
|
||||
mLocalAddr = addr;
|
||||
return( addr->resolve( host, port, proto ) );
|
||||
}
|
||||
bool resolveLocal( const char *serv, const char *proto )
|
||||
{
|
||||
SockAddrInet *addr = new SockAddrInet;
|
||||
mLocalAddr = addr;
|
||||
return( addr->resolve( serv, proto ) );
|
||||
}
|
||||
bool resolveLocal( int port, const char *proto )
|
||||
{
|
||||
SockAddrInet *addr = new SockAddrInet;
|
||||
mLocalAddr = addr;
|
||||
return( addr->resolve( port, proto ) );
|
||||
}
|
||||
bool connect( const char *host, const char *serv );
|
||||
bool connect( const char *host, int port );
|
||||
|
||||
bool resolveRemote( const char *host, const char *serv, const char *proto )
|
||||
{
|
||||
SockAddrInet *addr = new SockAddrInet;
|
||||
mRemoteAddr = addr;
|
||||
return( addr->resolve( host, serv, proto ) );
|
||||
}
|
||||
bool resolveRemote( const char *host, int port, const char *proto )
|
||||
{
|
||||
SockAddrInet *addr = new SockAddrInet;
|
||||
mRemoteAddr = addr;
|
||||
return( addr->resolve( host, port, proto ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
bool bind( const SockAddrInet &addr )
|
||||
{
|
||||
mLocalAddr = new SockAddrInet( addr );
|
||||
return( Socket::bind() );
|
||||
}
|
||||
bool bind( const char *host, const char *serv )
|
||||
{
|
||||
if ( !resolveLocal( host, serv, getProtocol() ) )
|
||||
return( false );
|
||||
return( Socket::bind() );
|
||||
}
|
||||
bool bind( const char *host, int port )
|
||||
{
|
||||
if ( !resolveLocal( host, port, getProtocol() ) )
|
||||
return( false );
|
||||
return( Socket::bind() );
|
||||
}
|
||||
bool bind( const char *serv )
|
||||
{
|
||||
if ( !resolveLocal( serv, getProtocol() ) )
|
||||
return( false );
|
||||
return( Socket::bind() );
|
||||
}
|
||||
bool bind( int port )
|
||||
{
|
||||
if ( !resolveLocal( port, getProtocol() ) )
|
||||
return( false );
|
||||
return( Socket::bind() );
|
||||
}
|
||||
|
||||
bool connect( const SockAddrInet &addr )
|
||||
{
|
||||
mRemoteAddr = new SockAddrInet( addr );
|
||||
return( Socket::connect() );
|
||||
}
|
||||
bool connect( const char *host, const char *serv )
|
||||
{
|
||||
if ( !resolveRemote( host, serv, getProtocol() ) )
|
||||
return( false );
|
||||
return( Socket::connect() );
|
||||
}
|
||||
bool connect( const char *host, int port )
|
||||
{
|
||||
if ( !resolveRemote( host, port, getProtocol() ) )
|
||||
return( false );
|
||||
return( Socket::connect() );
|
||||
}
|
||||
bool bind( const char *host, const char *serv );
|
||||
bool bind( const char *host, int port );
|
||||
bool bind( const char *serv );
|
||||
bool bind( int port );
|
||||
};
|
||||
|
||||
class UnixSocket : virtual public Socket
|
||||
|
@ -591,10 +515,6 @@ public:
|
|||
class UdpInetSocket : virtual public UdpSocket, virtual public InetSocket
|
||||
{
|
||||
public:
|
||||
bool bind( const SockAddrInet &addr )
|
||||
{
|
||||
return( InetSocket::bind( addr ) );
|
||||
}
|
||||
bool bind( const char *host, const char *serv )
|
||||
{
|
||||
return( InetSocket::bind( host, serv ) );
|
||||
|
@ -612,10 +532,6 @@ public:
|
|||
return( InetSocket::bind( port ) );
|
||||
}
|
||||
|
||||
bool connect( const SockAddrInet &addr )
|
||||
{
|
||||
return( InetSocket::connect( addr ) );
|
||||
}
|
||||
bool connect( const char *host, const char *serv )
|
||||
{
|
||||
return( InetSocket::connect( host, serv ) );
|
||||
|
@ -642,33 +558,7 @@ public:
|
|||
|
||||
class UdpInetClient : public UdpInetSocket
|
||||
{
|
||||
protected:
|
||||
bool bind( const SockAddrInet &addr )
|
||||
{
|
||||
return( UdpInetSocket::bind( addr ) );
|
||||
}
|
||||
bool bind( const char *host, const char *serv )
|
||||
{
|
||||
return( UdpInetSocket::bind( host, serv ) );
|
||||
}
|
||||
bool bind( const char *host, int port )
|
||||
{
|
||||
return( UdpInetSocket::bind( host, port ) );
|
||||
}
|
||||
bool bind( const char *serv )
|
||||
{
|
||||
return( UdpInetSocket::bind( serv ) );
|
||||
}
|
||||
bool bind( int port )
|
||||
{
|
||||
return( UdpInetSocket::bind( port ) );
|
||||
}
|
||||
|
||||
public:
|
||||
bool connect( const SockAddrInet &addr )
|
||||
{
|
||||
return( UdpInetSocket::connect( addr ) );
|
||||
}
|
||||
bool connect( const char *host, const char *serv )
|
||||
{
|
||||
return( UdpInetSocket::connect( host, serv ) );
|
||||
|
@ -697,10 +587,6 @@ public:
|
|||
class UdpInetServer : public UdpInetSocket
|
||||
{
|
||||
public:
|
||||
bool bind( const SockAddrInet &addr )
|
||||
{
|
||||
return( UdpInetSocket::bind( addr ) );
|
||||
}
|
||||
bool bind( const char *host, const char *serv )
|
||||
{
|
||||
return( UdpInetSocket::bind( host, serv ) );
|
||||
|
@ -812,18 +698,6 @@ public:
|
|||
class TcpInetServer : public TcpInetSocket
|
||||
{
|
||||
public:
|
||||
bool bind( const char *host, const char *serv )
|
||||
{
|
||||
return( TcpInetSocket::bind( host, serv ) );
|
||||
}
|
||||
bool bind( const char *host, int port )
|
||||
{
|
||||
return( TcpInetSocket::bind( host, port ) );
|
||||
}
|
||||
bool bind( const char *serv )
|
||||
{
|
||||
return( TcpInetSocket::bind( serv ) );
|
||||
}
|
||||
bool bind( int port )
|
||||
{
|
||||
return( TcpInetSocket::bind( port ) );
|
||||
|
|
|
@ -133,12 +133,11 @@ void zmLoadConfig()
|
|||
} else {
|
||||
Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID );
|
||||
}
|
||||
|
||||
}
|
||||
if ( ! staticConfig.SERVER_ID ) {
|
||||
Debug( 1, "No Server ID or Name specified in config. Not using Multi-Server Mode." );
|
||||
if ( staticConfig.SERVER_ID ) {
|
||||
Debug( 3, "Multi-server configuration detected. Server is %d.", staticConfig.SERVER_ID );
|
||||
} else {
|
||||
Debug( 1, "Server is %d: using Multi-Server Mode.", staticConfig.SERVER_ID );
|
||||
Debug( 3, "Single server configuration assumed because no Server ID or Name was specified." );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -170,12 +170,20 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
|
|||
#endif
|
||||
|
||||
/* Check the buffer sizes */
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t insize = av_image_get_buffer_size(in_pf, width, height,1);
|
||||
#else
|
||||
size_t insize = avpicture_get_size(in_pf, width, height);
|
||||
#endif
|
||||
if(insize != in_buffer_size) {
|
||||
Error("The input buffer size does not match the expected size for the input format. Required: %d Available: %d", insize, in_buffer_size);
|
||||
return -4;
|
||||
}
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
size_t outsize = av_image_get_buffer_size(out_pf, width, height,1);
|
||||
#else
|
||||
size_t outsize = avpicture_get_size(out_pf, width, height);
|
||||
#endif
|
||||
if(outsize < out_buffer_size) {
|
||||
Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size);
|
||||
return -5;
|
||||
|
|
|
@ -48,6 +48,10 @@ extern "C" {
|
|||
#else
|
||||
#include <libavcodec/opt.h>
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
#include <libavutil/imgutils.h>
|
||||
#endif
|
||||
#elif HAVE_FFMPEG_AVUTIL_H
|
||||
#include <ffmpeg/avutil.h>
|
||||
#include <ffmpeg/base64.h>
|
||||
|
|
|
@ -192,8 +192,13 @@ int FfmpegCamera::Capture( Image &image )
|
|||
if ( frameComplete )
|
||||
{
|
||||
Debug( 3, "Got frame %d", frameCount );
|
||||
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(mFrame->data, mFrame->linesize,
|
||||
directbuffer, imagePixFormat, width, height, 1);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer,
|
||||
imagePixFormat, width, height);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
if(mConvertContext == NULL) {
|
||||
|
@ -393,7 +398,12 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
|
||||
Debug ( 1, "Allocated frames" );
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int pSize = av_image_get_buffer_size( imagePixFormat, width, height,1 );
|
||||
#else
|
||||
int pSize = avpicture_get_size( imagePixFormat, width, height );
|
||||
#endif
|
||||
|
||||
if( (unsigned int)pSize != imagesize) {
|
||||
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
|
||||
}
|
||||
|
|
|
@ -644,7 +644,11 @@ LocalCamera::LocalCamera(
|
|||
if ( !tmpPicture )
|
||||
Fatal( "Could not allocate temporary picture" );
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int pSize = av_image_get_buffer_size( imagePixFormat, width, height,1 );
|
||||
#else
|
||||
int pSize = avpicture_get_size( imagePixFormat, width, height );
|
||||
#endif
|
||||
if( (unsigned int)pSize != imagesize) {
|
||||
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
|
||||
}
|
||||
|
@ -877,7 +881,18 @@ void LocalCamera::Initialise()
|
|||
#endif
|
||||
if ( !capturePictures[i] )
|
||||
Fatal( "Could not allocate picture" );
|
||||
avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height );
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(capturePictures[i]->data,
|
||||
capturePictures[i]->linesize,
|
||||
(uint8_t*)v4l2_data.buffers[i].start,capturePixFormat,
|
||||
v4l2_data.fmt.fmt.pix.width,
|
||||
v4l2_data.fmt.fmt.pix.height, 1);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)capturePictures[i],
|
||||
(uint8_t*)v4l2_data.buffers[i].start, capturePixFormat,
|
||||
v4l2_data.fmt.fmt.pix.width,
|
||||
v4l2_data.fmt.fmt.pix.height );
|
||||
#endif
|
||||
#endif // HAVE_LIBSWSCALE
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1050,16 @@ void LocalCamera::Initialise()
|
|||
#endif
|
||||
if ( !capturePictures[i] )
|
||||
Fatal( "Could not allocate picture" );
|
||||
avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height );
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(capturePictures[i]->data,
|
||||
capturePictures[i]->linesize,
|
||||
(unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i],
|
||||
capturePixFormat, width, height, 1);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)capturePictures[i],
|
||||
(unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i],
|
||||
capturePixFormat, width, height );
|
||||
#endif
|
||||
}
|
||||
#endif // HAVE_LIBSWSCALE
|
||||
|
||||
|
@ -2131,7 +2155,14 @@ int LocalCamera::Capture( Image &image )
|
|||
|
||||
Debug( 9, "Calling sws_scale to perform the conversion" );
|
||||
/* Use swscale to convert the image directly into the shared memory */
|
||||
avpicture_fill( (AVPicture *)tmpPicture, directbuffer, imagePixFormat, width, height );
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(tmpPicture->data,
|
||||
tmpPicture->linesize, directbuffer,
|
||||
imagePixFormat, width, height, 1);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)tmpPicture, directbuffer,
|
||||
imagePixFormat, width, height );
|
||||
#endif
|
||||
sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize );
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,11 @@
|
|||
#include <linux/videodev2.h>
|
||||
#endif // HAVE_LINUX_VIDEODEV2_H
|
||||
|
||||
// Required on systems with v4l1 but without v4l2 headers
|
||||
#ifndef VIDEO_MAX_FRAME
|
||||
#define VIDEO_MAX_FRAME 32
|
||||
#endif
|
||||
|
||||
#include "zm_ffmpeg.h"
|
||||
|
||||
//
|
||||
|
|
|
@ -333,7 +333,13 @@ void VideoStream::OpenStream( )
|
|||
Panic( "Could not allocate opicture" );
|
||||
}
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int size = av_image_get_buffer_size( c->pix_fmt, c->width,
|
||||
c->height, 1 );
|
||||
#else
|
||||
int size = avpicture_get_size( c->pix_fmt, c->width, c->height );
|
||||
#endif
|
||||
|
||||
uint8_t *opicture_buf = (uint8_t *)av_malloc( size );
|
||||
if ( !opicture_buf )
|
||||
{
|
||||
|
@ -344,7 +350,13 @@ void VideoStream::OpenStream( )
|
|||
#endif
|
||||
Panic( "Could not allocate opicture_buf" );
|
||||
}
|
||||
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, c->width, c->height );
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(opicture->data, opicture->linesize,
|
||||
opicture_buf, c->pix_fmt, c->width, c->height, 1);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt,
|
||||
c->width, c->height );
|
||||
#endif
|
||||
|
||||
/* if the output format is not identical to the input format, then a temporary
|
||||
picture is needed too. It is then converted to the required
|
||||
|
@ -361,7 +373,12 @@ void VideoStream::OpenStream( )
|
|||
{
|
||||
Panic( "Could not allocate tmp_opicture" );
|
||||
}
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int size = av_image_get_buffer_size( pf, c->width,
|
||||
c->height,1 );
|
||||
#else
|
||||
int size = avpicture_get_size( pf, c->width, c->height );
|
||||
#endif
|
||||
uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size );
|
||||
if ( !tmp_opicture_buf )
|
||||
{
|
||||
|
@ -372,7 +389,14 @@ void VideoStream::OpenStream( )
|
|||
#endif
|
||||
Panic( "Could not allocate tmp_opicture_buf" );
|
||||
}
|
||||
avpicture_fill( (AVPicture *)tmp_opicture, tmp_opicture_buf, pf, c->width, c->height );
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(tmp_opicture->data,
|
||||
tmp_opicture->linesize, tmp_opicture_buf, pf,
|
||||
c->width, c->height, 1);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)tmp_opicture,
|
||||
tmp_opicture_buf, pf, c->width, c->height );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -678,14 +702,14 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
|
|||
#endif
|
||||
if ( got_packet )
|
||||
{
|
||||
if ( c->coded_frame->key_frame )
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
|
||||
pkt->flags |= AV_PKT_FLAG_KEY;
|
||||
#else
|
||||
pkt->flags |= PKT_FLAG_KEY;
|
||||
#endif
|
||||
}
|
||||
// if ( c->coded_frame->key_frame )
|
||||
// {
|
||||
//#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
|
||||
// pkt->flags |= AV_PKT_FLAG_KEY;
|
||||
//#else
|
||||
// pkt->flags |= PKT_FLAG_KEY;
|
||||
//#endif
|
||||
// }
|
||||
|
||||
if ( pkt->pts != (int64_t)AV_NOPTS_VALUE )
|
||||
{
|
||||
|
|
|
@ -221,7 +221,12 @@ int RemoteCameraRtsp::PrimeCapture()
|
|||
if(mRawFrame == NULL || mFrame == NULL)
|
||||
Fatal( "Unable to allocate frame(s)");
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int pSize = av_image_get_buffer_size( imagePixFormat, width, height, 1 );
|
||||
#else
|
||||
int pSize = avpicture_get_size( imagePixFormat, width, height );
|
||||
#endif
|
||||
|
||||
if( (unsigned int)pSize != imagesize) {
|
||||
Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
|
||||
}
|
||||
|
@ -452,7 +457,13 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
|
|||
|
||||
Debug( 3, "Got frame %d", frameCount );
|
||||
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
av_image_fill_arrays(mFrame->data, mFrame->linesize,
|
||||
directbuffer, imagePixFormat, width, height, 1);
|
||||
#else
|
||||
avpicture_fill( (AVPicture *)mFrame, directbuffer,
|
||||
imagePixFormat, width, height);
|
||||
#endif
|
||||
|
||||
//Video recording
|
||||
if ( recording && !wasRecording ) {
|
||||
|
@ -524,8 +535,6 @@ int RemoteCameraRtsp::CaptureAndRecord( Image &image, bool recording, char* even
|
|||
return 0;
|
||||
}
|
||||
} else {
|
||||
Debug( 4, "Not storing audio" );
|
||||
}
|
||||
}
|
||||
} // end if video or audio packet
|
||||
|
||||
|
|
|
@ -279,20 +279,17 @@ int RtpCtrlThread::run()
|
|||
UdpInetSocket rtpCtrlServer;
|
||||
if ( mRtpSource.getLocalHost() != "" )
|
||||
{
|
||||
localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort(), "udp" );
|
||||
if ( !rtpCtrlServer.bind( localAddr ) )
|
||||
if ( !rtpCtrlServer.bind( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ) )
|
||||
Fatal( "Failed to bind RTCP server" );
|
||||
sendReports = false;
|
||||
Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() );
|
||||
}
|
||||
else
|
||||
{
|
||||
localAddr.resolve( mRtpSource.getLocalCtrlPort(), "udp" );
|
||||
if ( !rtpCtrlServer.bind( localAddr ) )
|
||||
if ( !rtpCtrlServer.bind( mRtspThread.getAddressFamily() == AF_INET6 ? "::" : "0.0.0.0", mRtpSource.getLocalCtrlPort() ) )
|
||||
Fatal( "Failed to bind RTCP server" );
|
||||
Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() );
|
||||
remoteAddr.resolve( mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort(), "udp" );
|
||||
if ( !rtpCtrlServer.connect( remoteAddr ) )
|
||||
if ( !rtpCtrlServer.connect( mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() ) )
|
||||
Fatal( "Failed to connect RTCP server" );
|
||||
Debug( 3, "Connected to %s:%d", mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() );
|
||||
sendReports = true;
|
||||
|
|
|
@ -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!)
|
||||
|
|
|
@ -67,13 +67,17 @@ int RtpDataThread::run()
|
|||
|
||||
SockAddrInet localAddr;
|
||||
UdpInetServer rtpDataSocket;
|
||||
if ( mRtpSource.getLocalHost() != "" )
|
||||
localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort(), "udp" );
|
||||
else
|
||||
localAddr.resolve( mRtpSource.getLocalDataPort(), "udp" );
|
||||
if ( !rtpDataSocket.bind( localAddr ) )
|
||||
if ( mRtpSource.getLocalHost() != "" ) {
|
||||
if ( !rtpDataSocket.bind( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() ) )
|
||||
Fatal( "Failed to bind RTP server" );
|
||||
Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !rtpDataSocket.bind( mRtspThread.getAddressFamily() == AF_INET6 ? "::" : "0.0.0.0", mRtpSource.getLocalDataPort() ) )
|
||||
Fatal( "Failed to bind RTP server" );
|
||||
Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() );
|
||||
}
|
||||
|
||||
Select select( 3 );
|
||||
select.addReader( &rtpDataSocket );
|
||||
|
|
|
@ -234,7 +234,7 @@ int RtspThread::run()
|
|||
|
||||
response.reserve( ZM_NETWORK_BUFSIZ );
|
||||
|
||||
if ( !mRtspSocket.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) )
|
||||
if ( !mRtspSocket.connect( mHost.c_str(), mPort.c_str() ) )
|
||||
Fatal( "Unable to connect RTSP socket" );
|
||||
//Select select( 0.25 );
|
||||
//select.addReader( &mRtspSocket );
|
||||
|
@ -248,7 +248,7 @@ int RtspThread::run()
|
|||
bool authTried = false;
|
||||
if ( mMethod == RTP_RTSP_HTTP )
|
||||
{
|
||||
if ( !mRtspSocket2.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) )
|
||||
if ( !mRtspSocket2.connect( mHost.c_str(), mPort.c_str() ) )
|
||||
Fatal( "Unable to connect auxiliary RTSP/HTTP socket" );
|
||||
//Select select( 0.25 );
|
||||
//select.addReader( &mRtspSocket2 );
|
||||
|
@ -306,7 +306,7 @@ int RtspThread::run()
|
|||
mAuthenticator->checkAuthResponse(response);
|
||||
Debug(2, "Processed 401 response");
|
||||
mRtspSocket.close();
|
||||
if ( !mRtspSocket.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) )
|
||||
if ( !mRtspSocket.connect( mHost.c_str(), mPort.c_str() ) )
|
||||
Fatal( "Unable to reconnect RTSP socket" );
|
||||
Debug(2, "connection should be reopened now");
|
||||
}
|
||||
|
|
|
@ -138,6 +138,10 @@ public:
|
|||
{
|
||||
return( mStop );
|
||||
}
|
||||
int getAddressFamily ()
|
||||
{
|
||||
return mRtspSocket.getDomain();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ZM_RTSP_H
|
||||
|
|
|
@ -112,7 +112,7 @@ SessionDescriptor::ConnInfo::ConnInfo( const std::string &connInfo ) :
|
|||
if ( mNetworkType != "IN" )
|
||||
throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" );
|
||||
mAddressType = tokens[1];
|
||||
if ( mAddressType != "IP4" )
|
||||
if ( mAddressType != "IP4" && mAddressType != "IP6" )
|
||||
throw Exception( "Invalid SDP address type '"+mAddressType+"' in connection info '"+connInfo+"'" );
|
||||
StringVector addressTokens = split( tokens[2], "/" );
|
||||
if ( addressTokens.size() < 1 )
|
||||
|
|
|
@ -291,7 +291,11 @@ 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 )
|
||||
|
@ -302,7 +306,6 @@ void StreamBase::openComms()
|
|||
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()
|
||||
|
|
|
@ -49,7 +49,7 @@ git submodule update --init --recursive
|
|||
if [ $DISTRO == "trusty" ]; then
|
||||
ln -sf distros/ubuntu1204 debian
|
||||
else
|
||||
ln -sf distros/ubuntu1504 debian
|
||||
ln -sf distros/ubuntu1604 debian
|
||||
fi;
|
||||
|
||||
# Auto-install all ZoneMinder's depedencies using the Debian control 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' );
|
||||
|
||||
?>
|
||||
|
|
|
@ -394,7 +394,7 @@ tr.log-dbg td {
|
|||
}
|
||||
|
||||
$exportFile = "zm-log.$exportExt";
|
||||
$exportPath = "temp/zm-log-$exportKey.$exportExt";
|
||||
$exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt";
|
||||
|
||||
header( "Pragma: public" );
|
||||
header( "Expires: 0" );
|
||||
|
|
|
@ -134,8 +134,10 @@ function loadConfigFile() {
|
|||
continue;
|
||||
elseif ( preg_match( '/^\s*#/', $str ))
|
||||
continue;
|
||||
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches ))
|
||||
Configure::write("$matches[1]", "$matches[2]");
|
||||
elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches )) {
|
||||
Configure::write( $matches[1], $matches[2] );
|
||||
define( $matches[1], $matches[2] );
|
||||
}
|
||||
}
|
||||
fclose( $cfg );
|
||||
}
|
||||
|
|
|
@ -67,10 +67,9 @@ class DATABASE_CONFIG {
|
|||
public $default = array(
|
||||
'datasource' => 'Database/Mysql',
|
||||
'persistent' => false,
|
||||
'host' => '@ZM_DB_HOST@',
|
||||
'login' => '@ZM_DB_USER@',
|
||||
'password' => '@ZM_DB_PASS@',
|
||||
'database' => '@ZM_DB_NAME@',
|
||||
'login' => ZM_DB_USER,
|
||||
'password' => ZM_DB_PASS,
|
||||
'database' => ZM_DB_NAME,
|
||||
'prefix' => '',
|
||||
//'encoding' => 'utf8',
|
||||
);
|
||||
|
@ -85,4 +84,18 @@ class DATABASE_CONFIG {
|
|||
'prefix' => '',
|
||||
//'encoding' => 'utf8',
|
||||
);
|
||||
|
||||
public function __construct() {
|
||||
if (strpos(ZM_DB_HOST, ':')):
|
||||
$array = explode(':', ZM_DB_HOST, 2);
|
||||
if (is_numeric($array[1])):
|
||||
$this->default['host'] = $array[0];
|
||||
$this->default['port'] = $array[1];
|
||||
else:
|
||||
$this->default['unix_socket'] = $array[1];
|
||||
endif;
|
||||
else:
|
||||
$this->default['host'] = ZM_DB_HOST;
|
||||
endif;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,11 +253,20 @@ public function beforeFilter() {
|
|||
|
||||
}
|
||||
|
||||
// format expected:
|
||||
// you can changed AlarmFrames to any other named params
|
||||
// consoleEvents/1 hour/AlarmFrames >=: 1/AlarmFrames <=: 20.json
|
||||
|
||||
public function consoleEvents($interval = null) {
|
||||
$this->Event->recursive = -1;
|
||||
$results = array();
|
||||
|
||||
$query = $this->Event->query("select MonitorId, COUNT(*) AS Count from Events WHERE StartTime >= (DATE_SUB(NOW(), interval $interval)) GROUP BY MonitorId;");
|
||||
$moreconditions ="";
|
||||
foreach ($this->request->params['named'] as $name => $param) {
|
||||
$moreconditions = $moreconditions . " AND ".$name.$param;
|
||||
}
|
||||
|
||||
$query = $this->Event->query("select MonitorId, COUNT(*) AS Count from Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;");
|
||||
|
||||
foreach ($query as $result) {
|
||||
$results[$result['Events']['MonitorId']] = $result[0]['Count'];
|
||||
|
|
|
@ -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,7 +138,8 @@ public function beforeFilter() {
|
|||
'_serialize' => array('message')
|
||||
));
|
||||
// - restart this monitor after change
|
||||
$this->daemonControl($this->Monitor->id, 'restart', $this->request->data);
|
||||
// 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' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,6 +184,86 @@ 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|status
|
||||
public function alarm()
|
||||
{
|
||||
$id = $this->request->params['named']['id'];
|
||||
$cmd = strtolower($this->request->params['named']['command']);
|
||||
if (!$this->Monitor->exists($id)) {
|
||||
throw new NotFoundException(__('Invalid monitor'));
|
||||
}
|
||||
if ( $cmd != 'on' && $cmd != 'off' && $cmd != 'status')
|
||||
{
|
||||
throw new BadRequestException(__('Invalid command'));
|
||||
}
|
||||
$zm_path_bin = Configure::read('ZM_PATH_BIN');
|
||||
|
||||
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');
|
||||
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH'));
|
||||
$config = $this->Config->find('first', $options);
|
||||
$zmOptAuth = $config['Config']['Value'];
|
||||
|
||||
|
||||
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY'));
|
||||
$config = $this->Config->find('first', $options);
|
||||
$zmAuthRelay = $config['Config']['Value'];
|
||||
|
||||
$auth="";
|
||||
if ($zmOptAuth)
|
||||
{
|
||||
if ($zmAuthRelay == 'hashed')
|
||||
{
|
||||
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_SECRET'));
|
||||
$config = $this->Config->find('first', $options);
|
||||
$zmAuthHashSecret = $config['Config']['Value'];
|
||||
|
||||
$time = localtime();
|
||||
$ak = $zmAuthHashSecret.$this->Session->Read('username').$this->Session->Read('passwordHash').$time[2].$time[3].$time[4].$time[5];
|
||||
$ak = md5($ak);
|
||||
$auth = " -A ".$ak;
|
||||
}
|
||||
elseif ($zmAuthRelay == 'plain')
|
||||
{
|
||||
$auth = " -U " .$this->Session->Read('username')." -P ".$this->Session->Read('password');
|
||||
|
||||
}
|
||||
elseif ($zmAuthRelay == 'none')
|
||||
{
|
||||
$auth = " -U " .$this->Session->Read('username');
|
||||
}
|
||||
}
|
||||
|
||||
$shellcmd = escapeshellcmd("$zm_path_bin/zmu $verbose -m$id $q $auth");
|
||||
$status = exec ($shellcmd);
|
||||
|
||||
$this->set(array(
|
||||
'status' => $status,
|
||||
'_serialize' => array('status'),
|
||||
));
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Check if a daemon is running for the monitor id
|
||||
public function daemonStatus() {
|
||||
$id = $this->request->params['named']['id'];
|
||||
|
|
|
@ -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'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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' => ''
|
||||
)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
echo json_encode($message);
|
||||
echo json_encode($server);
|
|
@ -0,0 +1 @@
|
|||
echo json_encode($servers);
|
|
@ -0,0 +1 @@
|
|||
echo json_encode($server);
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $message));
|
||||
echo $xml->asXML();
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $monitors));
|
||||
echo $xml->asXML();
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $monitor));
|
||||
echo $xml->asXML();
|
|
@ -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='&' ) {
|
||||
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
|
||||
?>
|
|
@ -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 $_SERVER['PHP_SELF'].'?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
|
||||
?>
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
require_once( 'database.php' );
|
||||
class Server {
|
||||
|
||||
class Server {
|
||||
public function __construct( $IdOrRow = NULL ) {
|
||||
$row = NULL;
|
||||
if ( $IdOrRow ) {
|
||||
|
@ -49,9 +49,36 @@ class Server {
|
|||
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);
|
||||
#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];
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue