From 155835367249752a6c652a49f0fe6b18335bcdf7 Mon Sep 17 00:00:00 2001 From: "Jan M. Hochstein" Date: Sat, 9 Apr 2016 17:07:11 +0200 Subject: [PATCH 01/49] Force UTF-8 when sending WS-Discovery Probe --- onvif/modules/lib/WSDiscovery/TransportUDP.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/onvif/modules/lib/WSDiscovery/TransportUDP.pm b/onvif/modules/lib/WSDiscovery/TransportUDP.pm index 375f9628d..edc837da6 100644 --- a/onvif/modules/lib/WSDiscovery/TransportUDP.pm +++ b/onvif/modules/lib/WSDiscovery/TransportUDP.pm @@ -61,16 +61,19 @@ sub _notify_response } sub send_multi() { - my ($self, $address, $port, $data) = @_; + my ($self, $address, $port, $utf8_string) = @_; my $destination = $address . ':' . $port; my $socket = IO::Socket::Multicast->new(PROTO => 'udp', LocalPort=>$port, PeerAddr=>$destination, ReuseAddr=>1) or die 'Cannot open multicast socket to ' . ${address} . ':' . ${port}; + + my $bytes = $utf8_string; + utf8::encode($bytes); $socket->mcast_ttl(1); - $socket->send($data); + $socket->send($bytes); } sub receive_multi() { From 2125faa4447dfd146fe6448f2bd3f6461f4c4bbd Mon Sep 17 00:00:00 2001 From: "Jan M. Hochstein" Date: Sun, 10 Apr 2016 09:37:16 +0200 Subject: [PATCH 02/49] Added header elements to perl WS-Discovery proxy --- .../WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm | 6 +++++- onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm b/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm index d194bbc87..581d6e59e 100644 --- a/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm +++ b/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm @@ -34,7 +34,11 @@ sub ProbeOp { }, header => { - + 'use' => 'literal', + namespace => 'http://schemas.xmlsoap.org/ws/2004/08/addressing', + encodingStyle => '', + parts => [qw(WSDiscovery10::Elements::To WSDiscovery10::Elements::Action)], + }, headerfault => { diff --git a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm index 635a19393..4429a517b 100644 --- a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm +++ b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm @@ -24,6 +24,11 @@ our $typemap_1 = { 'ProbeMatches/ProbeMatch/EndpointReference' => 'WSDiscovery10::Types::EndpointReferenceType', 'ProbeMatches/ProbeMatch/EndpointReference/ReferenceProperties' => 'WSDiscovery10::Types::ReferencePropertiesType', 'ProbeMatches/ProbeMatch/EndpointReference/PortType' => 'WSDiscovery10::Types::AttributedQName' + 'MessageID' => 'WSDiscovery10::Elements::MessageID', + 'RelatesTo' => '__SKIP__', + 'To' => '__SKIP__', + 'Action' => '__SKIP__', + 'AppSequence' => '__SKIP__', }; ; From edf3f3c43a1e197b4627d0ba11ec4a478e9b2517 Mon Sep 17 00:00:00 2001 From: "Jan M. Hochstein" Date: Sun, 10 Apr 2016 15:57:53 +0200 Subject: [PATCH 03/49] Fixed WS-Discovery Probe message header --- .../lib/WSDiscovery10/Elements/Header.pm | 55 +++++++++++++++++++ .../lib/WSDiscovery10/Typemaps/WSDiscovery.pm | 8 +-- onvif/scripts/zmonvif-probe.pl | 23 +++++++- 3 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 onvif/proxy/lib/WSDiscovery10/Elements/Header.pm diff --git a/onvif/proxy/lib/WSDiscovery10/Elements/Header.pm b/onvif/proxy/lib/WSDiscovery10/Elements/Header.pm new file mode 100644 index 000000000..df2d7f389 --- /dev/null +++ b/onvif/proxy/lib/WSDiscovery10/Elements/Header.pm @@ -0,0 +1,55 @@ + +package WSDiscovery10::Elements::Header; +use strict; +use warnings; + + +__PACKAGE__->_set_element_form_qualified(0); + +sub get_xmlns { 'http://schemas.xmlsoap.org/soap/envelope/' }; + +our $XML_ATTRIBUTE_CLASS; +undef $XML_ATTRIBUTE_CLASS; + +sub __get_attr_class { + return $XML_ATTRIBUTE_CLASS; +} + +use Class::Std::Fast::Storable constructor => 'none'; +use base qw(SOAP::WSDL::XSD::Typelib::ComplexType); + +Class::Std::initialize(); + +{ # BLOCK to scope variables + +my %Action_of :ATTR(:get); +my %MessageID_of :ATTR(:get); +my %ReplyTo_of :ATTR(:get); +my %To_of :ATTR(:get); + +__PACKAGE__->_factory( + [ qw( Action MessageID ReplyTo To ) ], + { + 'Action' => \%Action_of, + 'MessageID' => \%MessageID_of, + 'ReplyTo' => \%ReplyTo_of, + 'To' => \%To_of, + }, + { + 'Action' => 'WSDiscovery10::Elements::Action', + 'MessageID' => 'WSDiscovery10::Elements::MessageID', + 'ReplyTo' => 'WSDiscovery10::Elements::ReplyTo', + 'To' => 'WSDiscovery10::Elements::To', + }, + { + 'Action' => '', + 'MessageID' => '', + 'ReplyTo' => '', + 'To' => '', + } +); + +} # end BLOCK + + +1; diff --git a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm index 4429a517b..f0d7b7931 100644 --- a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm +++ b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm @@ -25,10 +25,10 @@ our $typemap_1 = { 'ProbeMatches/ProbeMatch/EndpointReference/ReferenceProperties' => 'WSDiscovery10::Types::ReferencePropertiesType', 'ProbeMatches/ProbeMatch/EndpointReference/PortType' => 'WSDiscovery10::Types::AttributedQName' 'MessageID' => 'WSDiscovery10::Elements::MessageID', - 'RelatesTo' => '__SKIP__', - 'To' => '__SKIP__', - 'Action' => '__SKIP__', - 'AppSequence' => '__SKIP__', + 'RelatesTo' => 'WSDiscovery10::Elements::RelatesTo', + 'To' => 'WSDiscovery10::Elements::To', + 'Action' => 'WSDiscovery10::Elements::Action', + 'AppSequence' => 'WSDiscovery10::Elements::AppSequence', }; ; diff --git a/onvif/scripts/zmonvif-probe.pl b/onvif/scripts/zmonvif-probe.pl index 93c12959f..8f1fccd17 100755 --- a/onvif/scripts/zmonvif-probe.pl +++ b/onvif/scripts/zmonvif-probe.pl @@ -25,13 +25,14 @@ # use Getopt::Std; +use Data::UUID; require ONVIF::Client; require WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort; +require WSDiscovery10::Elements::Header; require WSDiscovery10::Elements::Types; require WSDiscovery10::Elements::Scopes; -require WSDiscovery10::Elements::To; require WSDiscovery::TransportUDP; @@ -169,6 +170,8 @@ sub discover ## try both soap versions my %services; + my $uuid_gen = Data::UUID->new(); + if($verbose) { print "Probing for SOAP 1.1\n" } @@ -177,12 +180,18 @@ sub discover }); $svc_discover->set_soap_version('1.1'); + my $uuid = $uuid_gen->create_str(); + my $result = $svc_discover->ProbeOp( { # WSDiscovery::Types::ProbeType Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType Scopes => { value => '' }, }, - WSDiscovery10::Elements::To->new({ value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }) + WSDiscovery10::Elements::Header->new({ + Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' }, + MessageID => { value => "urn:uuid:$uuid" }, + To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }, + }) ); # print $result . "\n"; @@ -197,12 +206,20 @@ 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 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"; From 8b92151a0cb75c312d252e88a9759741f4367f85 Mon Sep 17 00:00:00 2001 From: "Jan M. Hochstein" Date: Sun, 10 Apr 2016 18:19:10 +0200 Subject: [PATCH 04/49] WS-Discovery header fixes --- .../Interfaces/WSDiscovery/WSDiscoveryPort.pm | 2 +- .../proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm b/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm index 581d6e59e..f1b6446a5 100644 --- a/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm +++ b/onvif/proxy/lib/WSDiscovery10/Interfaces/WSDiscovery/WSDiscoveryPort.pm @@ -37,7 +37,7 @@ sub ProbeOp { 'use' => 'literal', namespace => 'http://schemas.xmlsoap.org/ws/2004/08/addressing', encodingStyle => '', - parts => [qw(WSDiscovery10::Elements::To WSDiscovery10::Elements::Action)], + parts => [qw( WSDiscovery10::Elements::Header )], }, headerfault => { diff --git a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm index f0d7b7931..c19a7c647 100644 --- a/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm +++ b/onvif/proxy/lib/WSDiscovery10/Typemaps/WSDiscovery.pm @@ -23,12 +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' - 'MessageID' => 'WSDiscovery10::Elements::MessageID', - 'RelatesTo' => 'WSDiscovery10::Elements::RelatesTo', - 'To' => 'WSDiscovery10::Elements::To', - 'Action' => 'WSDiscovery10::Elements::Action', - 'AppSequence' => 'WSDiscovery10::Elements::AppSequence', + 'ProbeMatches/ProbeMatch/EndpointReference/PortType' => 'WSDiscovery10::Types::AttributedQName', + 'MessageID' => '__SKIP__', + 'RelatesTo' => '__SKIP__', + 'To' => '__SKIP__', + 'Action' => '__SKIP__', + 'AppSequence' => '__SKIP__', }; ; From 2b05815bfa0c36aae5d486d6d77882db7f6128f6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 15 Apr 2016 15:44:35 -0400 Subject: [PATCH 05/49] remove set height on the menu bars, fixing flow issues --- web/skins/classic/css/classic/views/event.css | 12 ++++++++++-- web/skins/classic/css/dark/views/event.css | 12 ++++++++++-- web/skins/classic/css/flat/views/event.css | 11 +++++++++-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/web/skins/classic/css/classic/views/event.css b/web/skins/classic/css/classic/views/event.css index 995a06c1d..13ac0cc0b 100644 --- a/web/skins/classic/css/classic/views/event.css +++ b/web/skins/classic/css/classic/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,16 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} + #imageFeed { text-align: center; } diff --git a/web/skins/classic/css/dark/views/event.css b/web/skins/classic/css/dark/views/event.css index 995a06c1d..13ac0cc0b 100644 --- a/web/skins/classic/css/dark/views/event.css +++ b/web/skins/classic/css/dark/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,16 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} + #imageFeed { text-align: center; } diff --git a/web/skins/classic/css/flat/views/event.css b/web/skins/classic/css/flat/views/event.css index 17c4f70cf..e69fe14f6 100644 --- a/web/skins/classic/css/flat/views/event.css +++ b/web/skins/classic/css/flat/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,15 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} #imageFeed { text-align: center; } From 5d3f5e5a4a14b7af57f246e62ae2f5a195b22690 Mon Sep 17 00:00:00 2001 From: "Jan M. Hochstein" Date: Sat, 16 Apr 2016 19:06:36 +0200 Subject: [PATCH 06/49] WSDiscovery: workaround for SOAP::WSDL QName limitation --- .../lib/WSDiscovery10/Types/ProbeType.pm | 50 ++++++++++++++++++- onvif/scripts/zmonvif-probe.pl | 4 +- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm b/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm index 10c290e8e..8d7e9e7ca 100644 --- a/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm +++ b/onvif/proxy/lib/WSDiscovery10/Types/ProbeType.pm @@ -7,8 +7,10 @@ __PACKAGE__->_set_element_form_qualified(0); sub get_xmlns { 'http://schemas.xmlsoap.org/ws/2005/04/discovery' }; -our $XML_ATTRIBUTE_CLASS; -undef $XML_ATTRIBUTE_CLASS; +our $XML_ATTRIBUTE_CLASS = 'WSDiscovery10::Types::ProbeType::_ProbeType::XmlAttr'; + +#our $XML_ATTRIBUTE_CLASS; +#undef $XML_ATTRIBUTE_CLASS; sub __get_attr_class { return $XML_ATTRIBUTE_CLASS; @@ -49,11 +51,55 @@ __PACKAGE__->_factory( } # end BLOCK +package WSDiscovery10::Types::ProbeType::_ProbeType::XmlAttr; +#use base qw(SOAP::WSDL::XSD::Typelib::ComplexType); +use Class::Std::Fast::Storable constructor => 'none', cache => 1; +use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType); +{ # BLOCK to scope variables +my %Attribs_of :ATTR(:get); +sub new +{ + my $self = pop @{ Class::Std::Fast::OBJECT_CACHE_REF()->{ $_[0] } }; + $self = bless \(my $o = Class::Std::Fast::ID()), $_[0] + if not defined $self; + + $self->BUILD(${$self}, $_[1]); + return $self; +} + +sub BUILD +{ + my ($self, $ident, $arg_ref) = @_; + + $Attribs_of{$ident} = $arg_ref; +} + +# without this no attributes are serialized +# SOAP::WSDL::XSD::Typelib::CompexType sub serialize_attr() + +sub as_bool :BOOLIFY { 1 } + +sub serialize() +{ + my $ident = ${ $_[0] }; + my $option_ref = $_[1]; + my $attr_str = ""; + + foreach my $attr (keys %{$Attribs_of{$ident}}) + { + my $value = %{$Attribs_of{$ident}}{$attr}; + $attr_str .= " $attr=\"$value\""; + } + + return $attr_str; +} + +} # end BLOCK 1; diff --git a/onvif/scripts/zmonvif-probe.pl b/onvif/scripts/zmonvif-probe.pl index 8f1fccd17..10aa26a08 100755 --- a/onvif/scripts/zmonvif-probe.pl +++ b/onvif/scripts/zmonvif-probe.pl @@ -212,7 +212,9 @@ sub discover $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::Header->new({ From 0dc2987b84e12640bb793b188aae2b42d3e0724b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 28 Apr 2016 16:32:50 -0400 Subject: [PATCH 07/49] add some error checking, but fix the call to bind which really should have a +1 in it. --- src/zm_stream.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index 77c94e68c..eb15fe02c 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -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 ) @@ -318,12 +322,19 @@ void StreamBase::openComms() 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) ); } From 75f9fde9202a1f644e0ab3de9474a603a16d7a59 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 May 2016 10:37:19 -0400 Subject: [PATCH 08/49] rough in Server object support --- web/api/app/Controller/ServersController.php | 155 +++++++++++++++++++ web/api/app/Model/Server.php | 74 +++++++++ web/api/app/View/Servers/json/edit.ctp | 2 + web/api/app/View/Servers/json/index.ctp | 1 + web/api/app/View/Servers/json/view.ctp | 1 + web/api/app/View/Servers/xml/edit.ctp | 2 + web/api/app/View/Servers/xml/index.ctp | 2 + web/api/app/View/Servers/xml/view.ctp | 2 + 8 files changed, 239 insertions(+) create mode 100644 web/api/app/Controller/ServersController.php create mode 100644 web/api/app/Model/Server.php create mode 100644 web/api/app/View/Servers/json/edit.ctp create mode 100644 web/api/app/View/Servers/json/index.ctp create mode 100644 web/api/app/View/Servers/json/view.ctp create mode 100644 web/api/app/View/Servers/xml/edit.ctp create mode 100644 web/api/app/View/Servers/xml/index.ctp create mode 100644 web/api/app/View/Servers/xml/view.ctp diff --git a/web/api/app/Controller/ServersController.php b/web/api/app/Controller/ServersController.php new file mode 100644 index 000000000..b9afe0033 --- /dev/null +++ b/web/api/app/Controller/ServersController.php @@ -0,0 +1,155 @@ +Session->Read('systemPermission'); + if ($canView =='None') { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } + +} + + +/** + * index method + * + * @return void + */ + public function index() { + $this->Server->recursive = 0; + + $options=''; + $servers = $this->Server->find('all',$options); + $this->set(array( + 'servers' => $servers, + '_serialize' => array('servers') + )); + } + +/** + * view method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function view($id = null) { + $this->Server->recursive = 0; + if (!$this->Server->exists($id)) { + throw new NotFoundException(__('Invalid server')); + } + $restricted = ''; + + $options = array('conditions' => array( + array('Server.' . $this->Server->primaryKey => $id), + $restricted + ) + ); + $server = $this->Server->find('first', $options); + $this->set(array( + 'server' => $server, + '_serialize' => array('server') + )); + } + +/** + * add method + * + * @return void + */ + public function add() { + if ($this->request->is('post')) { + + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + + $this->Server->create(); + if ($this->Server->save($this->request->data)) { + # Might be nice to send it a start request + #$this->daemonControl($this->Server->id, 'start', $this->request->data); + return $this->flash(__('The server has been saved.'), array('action' => 'index')); + } + } + } + +/** + * edit method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function edit($id = null) { + $this->Server->id = $id; + + if (!$this->Server->exists($id)) { + throw new NotFoundException(__('Invalid server')); + } + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + if ($this->Server->save($this->request->data)) { + $message = 'Saved'; + } else { + $message = 'Error'; + } + + $this->set(array( + 'message' => $message, + '_serialize' => array('message') + )); + // - restart this server after change + #$this->daemonControl($this->Server->id, 'restart', $this->request->data); + } + +/** + * delete method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function delete($id = null) { + $this->Server->id = $id; + if (!$this->Server->exists()) { + throw new NotFoundException(__('Invalid server')); + } + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + $this->request->allowMethod('post', 'delete'); + + #$this->daemonControl($this->Server->id, 'stop'); + + if ($this->Server->delete()) { + return $this->flash(__('The server has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The server could not be deleted. Please, try again.'), array('action' => 'index')); + } + } +} diff --git a/web/api/app/Model/Server.php b/web/api/app/Model/Server.php new file mode 100644 index 000000000..b58450db5 --- /dev/null +++ b/web/api/app/Model/Server.php @@ -0,0 +1,74 @@ + array( + 'numeric' => array( + 'rule' => array('numeric'), + //'message' => 'Your custom message here', + //'allowEmpty' => false, + //'required' => false, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * hasMany associations + * + * @var array + */ + public $hasMany = array( + 'Monitor' => array( + 'className' => 'Monitor', + 'foreignKey' => 'ServerId', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); +} diff --git a/web/api/app/View/Servers/json/edit.ctp b/web/api/app/View/Servers/json/edit.ctp new file mode 100644 index 000000000..0be859571 --- /dev/null +++ b/web/api/app/View/Servers/json/edit.ctp @@ -0,0 +1,2 @@ +echo json_encode($message); +echo json_encode($server); diff --git a/web/api/app/View/Servers/json/index.ctp b/web/api/app/View/Servers/json/index.ctp new file mode 100644 index 000000000..6e5cbd26d --- /dev/null +++ b/web/api/app/View/Servers/json/index.ctp @@ -0,0 +1 @@ +echo json_encode($servers); diff --git a/web/api/app/View/Servers/json/view.ctp b/web/api/app/View/Servers/json/view.ctp new file mode 100644 index 000000000..c3d0226ab --- /dev/null +++ b/web/api/app/View/Servers/json/view.ctp @@ -0,0 +1 @@ +echo json_encode($server); diff --git a/web/api/app/View/Servers/xml/edit.ctp b/web/api/app/View/Servers/xml/edit.ctp new file mode 100644 index 000000000..09fb8979a --- /dev/null +++ b/web/api/app/View/Servers/xml/edit.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $message)); +echo $xml->asXML(); diff --git a/web/api/app/View/Servers/xml/index.ctp b/web/api/app/View/Servers/xml/index.ctp new file mode 100644 index 000000000..37afc918b --- /dev/null +++ b/web/api/app/View/Servers/xml/index.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $monitors)); +echo $xml->asXML(); diff --git a/web/api/app/View/Servers/xml/view.ctp b/web/api/app/View/Servers/xml/view.ctp new file mode 100644 index 000000000..b33c6e79a --- /dev/null +++ b/web/api/app/View/Servers/xml/view.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $monitor)); +echo $xml->asXML(); From 01aa2c931940794a75348e5d3213dee015ec737d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 May 2016 19:48:24 -0400 Subject: [PATCH 09/49] change permissions to stream permissions for view --- web/api/app/Controller/ServersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/api/app/Controller/ServersController.php b/web/api/app/Controller/ServersController.php index b9afe0033..88a5bec90 100644 --- a/web/api/app/Controller/ServersController.php +++ b/web/api/app/Controller/ServersController.php @@ -19,7 +19,7 @@ class ServersController extends AppController { public function beforeFilter() { parent::beforeFilter(); - $canView = $this->Session->Read('systemPermission'); + $canView = $this->Session->Read('streamPermission'); if ($canView =='None') { throw new UnauthorizedException(__('Insufficient Privileges')); return; From 55d58a140e8f376bd6264912a0ddabc66f3a5c38 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 08:57:51 -0400 Subject: [PATCH 10/49] instead of code duplication for opening the db, use zmDbConnect everywhere --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 24 ++++----------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index a6a82db87..4c5acac2b 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -30,6 +30,7 @@ use warnings; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -460,25 +461,7 @@ sub databaseLevel { if ( !$this->{dbh} ) { - my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); - - if ( defined($port) ) - { - $this->{dbh} = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$host - .";port=".$port - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} - ); - } - else - { - $this->{dbh} = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$Config{ZM_DB_HOST} - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} - ); - } + $this->{dbh} = zmDbConnect(); if ( !$this->{dbh} ) { $databaseLevel = NOLOG; @@ -505,7 +488,8 @@ sub databaseLevel { if ( $this->{dbh} ) { - $this->{dbh}->disconnect(); + # $this->dbh is now the global dbh, so don't close it. + #$this->{dbh}->disconnect(); undef($this->{dbh}); } } From 30f34a6f49f071b8f2f912d1a177cc7ab13a4a05 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 08:59:40 -0400 Subject: [PATCH 11/49] instead of code duplication for opening the db, use zmDbConnect everywhere --- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 3a226cdc8..4be86e962 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -30,6 +30,7 @@ use warnings; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -82,12 +83,7 @@ BEGIN } close( $CONFIG ); - use DBI; - my $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$Config{ZM_DB_HOST} - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} - ) or croak( "Can't connect to db" ); + my $dbh = zmDbConnect() or croak( "Can't connect to db" ); 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() ); @@ -95,7 +91,6 @@ BEGIN $Config{$config->{Name}} = $config->{Value}; } $sth->finish(); - #$dbh->disconnect(); if ( ! exists $Config{ZM_SERVER_ID} ) { $Config{ZM_SERVER_ID} = undef; From 9406a2337f5fd20ed5a7af3a62d58f49b825d9b2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:21:01 -0400 Subject: [PATCH 12/49] Add a BEGIN section to load things in the correct order. --- scripts/ZoneMinder/lib/ZoneMinder.pm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder.pm b/scripts/ZoneMinder/lib/ZoneMinder.pm index 87a6b14b7..37292a44d 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder.pm @@ -81,6 +81,13 @@ our @EXPORT = ( @EXPORT_OK ); our $VERSION = $ZoneMinder::Base::VERSION; +BEGIN { + require ZoneMinder::Config; + require ZoneMinder::Database; + ZoneMinder::Config::zmConfigLoad(); + ZoneMinder::Database::zmDbConnect(); +} + 1; __END__ From 49e3d3be7aaafdb9975719207e44134dbf210b24 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:21:50 -0400 Subject: [PATCH 13/49] Turn the config loading code from a BEGIN to a function that could be called repeatedly. --- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 4be86e962..03f05d0e8 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -30,7 +30,6 @@ use warnings; require Exporter; require ZoneMinder::Base; -require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -64,8 +63,9 @@ use constant ZM_CONFIG => "@ZM_CONFIG@"; # Path to the ZoneMinder config file use Carp; # Load the config from the database into the symbol table -BEGIN -{ +sub zmConfigLoad { + %Config = (); + my $config_file = ZM_CONFIG; open( my $CONFIG, "<", $config_file ) or croak( "Can't open config file '$config_file': $!" ); @@ -83,7 +83,8 @@ BEGIN } close( $CONFIG ); - my $dbh = zmDbConnect() or croak( "Can't connect to db" ); + require ZoneMinder::Database; + my $dbh = ZoneMinder::Database::zmDbConnect() or croak( "Can't connect to db" ); 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() ); From e80db4c4339c4a86f4583899cb882104aa3883d3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:22:16 -0400 Subject: [PATCH 14/49] Use zmDbConnect instead of duplicated db connect code --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 4c5acac2b..0e454d784 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -461,7 +461,7 @@ sub databaseLevel { if ( !$this->{dbh} ) { - $this->{dbh} = zmDbConnect(); + $this->{dbh} = ZoneMinder::Database::zmDbConnect(); if ( !$this->{dbh} ) { $databaseLevel = NOLOG; From 24bf91707f0119fef79af05e8fe0e48917870968 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:22:38 -0400 Subject: [PATCH 15/49] Database module should really use DBI --- scripts/ZoneMinder/lib/ZoneMinder/Database.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm index 7dfe0654b..fdea725fe 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm @@ -27,6 +27,7 @@ package ZoneMinder::Database; use 5.006; use strict; use warnings; +use DBI; require Exporter; require ZoneMinder::Base; From c0509691412fa8312968ed31fb773d050a7922d1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 5 May 2016 15:33:28 -0400 Subject: [PATCH 16/49] Merge object model classes from storageareas --- web/includes/Event.php | 152 +++++++++++++++++++++++++++++++++++++++ web/includes/Frame.php | 103 ++++++++++++++++++++++++++ web/includes/Server.php | 79 +++++++++++++------- web/includes/Storage.php | 51 +++++++++++++ 4 files changed, 359 insertions(+), 26 deletions(-) create mode 100644 web/includes/Event.php create mode 100644 web/includes/Frame.php create mode 100644 web/includes/Storage.php diff --git a/web/includes/Event.php b/web/includes/Event.php new file mode 100644 index 000000000..5ad1c4031 --- /dev/null +++ b/web/includes/Event.php @@ -0,0 +1,152 @@ + $v) { + $this->{$k} = $v; + } + } else { + Error("No row for Event " . $IdOrRow ); + } + } // end function __construct + public function Storage() { + return new Storage( $this->{'StorageId'} ); + } + public function __call( $fn, array $args){ + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); + } + } + + public function Time() { + if ( ! isset( $this->{'Time'} ) ) { + $this->{'Time'} = strtotime($this->{'StartTime'}); + } + return $this->{'Time'}; + } + + public function Path() { + $Storage = $this->Storage(); + return $Storage->Path().'/'.$this->Relative_Path(); + } + public function Relative_Path() { + $event_path = ""; + + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = + $this->{'MonitorId'} + .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $this->Time() + ) + ; + } + else + { + $event_path = + $this->{'MonitorId'} + .'/'.$this->{'Id'} + ; + } + + return( $event_path ); + + } + + public function LinkPath() { + if ( ZM_USE_DEEP_STORAGE ) { + return $this->{'MonitorId'} .'/'.strftime( "%y/%m/%d/.", $this->Time()).$this->{'Id'}; + } + Error("Calling Link_Path when not using deep storage"); + return ''; + } + + public function delete() { + dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) ); + if ( !ZM_OPT_FAST_DELETE ) { + dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) ); + dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}) ); + if ( ZM_USE_DEEP_STORAGE ) { + +# Assumption: All events haev a start time + $start_date = date_parse( $this->{'StartTime'} ); + $start_date['year'] = $start_date['year'] % 100; + + $Storage = $this->Storage(); +# So this is because ZM creates a link under teh day pointing to the time that the event happened. + $eventlink_path = $Storage->Path().'/'.$this->Link_Path(); + + if ( $id_files = glob( $eventlink_path ) ) { +# I know we are using arrays here, but really there can only ever be 1 in the array + $eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] ); + deletePath( $eventPath ); + deletePath( $id_files[0] ); + $pathParts = explode( '/', $eventPath ); + for ( $i = count($pathParts)-1; $i >= 2; $i-- ) { + $deletePath = join( '/', array_slice( $pathParts, 0, $i ) ); + if ( !glob( $deletePath."/*" ) ) { + deletePath( $deletePath ); + } + } + } else { + Warning( "Found no event files under $eventlink_path" ); + } # end if found files + } else { + $eventPath = $this->Path(); + deletePath( $eventPath ); + } # USE_DEEP_STORAGE OR NOT + } # ! ZM_OPT_FAST_DELETE + } # end Event->delete + +public function getStreamSrc( $args, $querySep='&' ) { + return ZM_BASE_URL.'/index.php?view=view_video&eid='.$this->{'Id'}; + + $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; + + $args[] = "source=event&event=".$this->{'Id'}; + + if ( ZM_OPT_USE_AUTH ) { + if ( ZM_AUTH_RELAY == "hashed" ) { + $args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS ); + } elseif ( ZM_AUTH_RELAY == "plain" ) { + $args[] = "user=".$_SESSION['username']; + $args[] = "pass=".$_SESSION['password']; + } elseif ( ZM_AUTH_RELAY == "none" ) { + $args[] = "user=".$_SESSION['username']; + } + } + if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) { + $args[] = "connkey=".$GLOBALS['connkey']; + } + if ( ZM_RAND_STREAM ) { + $args[] = "rand=".time(); + } + + if ( count($args) ) { + $streamSrc .= "?".join( $querySep, $args ); + } + + return( $streamSrc ); + } // end function getStreamSrc +} # end class +?> diff --git a/web/includes/Frame.php b/web/includes/Frame.php new file mode 100644 index 000000000..5973cd1bf --- /dev/null +++ b/web/includes/Frame.php @@ -0,0 +1,103 @@ + $v) { + $this->{$k} = $v; + } + } else { + Error("No row for Frame " . $IdOrRow ); + } + } // end function __construct + public function Storage() { + return $this->Event()->Storage(); + } + public function Event() { + return new Event( $this->{'EventId'} ); + } + public function __call( $fn, array $args){ + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); + } + } + + public function Path() { + $Storage = $this->Storage(); + return $Storage->Path().'/'.$this->Relative_Path(); + } + public function Relative_Path() { + $event_path = ""; + + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = + $this->{'MonitorId'} + .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $this->Time() + ) + ; + } + else + { + $event_path = + $this->{'MonitorId'} + .'/'.$this->{'Id'} + ; + } + + return( $event_path ); + + } + + public function getImageSrc( ) { + return ZM_BASE_URL.'/index.php?view=image&fid='.$this->{'Id'}; + } // end function getImageSrc + + public static function find( $parameters = array(), $limit = NULL ) { + $sql = 'SELECT * FROM Frames'; + $values = array(); + if ( sizeof($parameters) ) { + $sql .= ' WHERE ' . implode( ' AND ', array_map( + function($v){ return $v.'=?'; }, + array_keys( $parameters ) + ) ); + $values = array_values( $parameters ); + } + if ( $limit ) { + $sql .= ' LIMIT ' . $limit; + } + $results = dbFetchAll( $sql, NULL, $values ); + if ( $results ) { + return array_map( function($id){ return new Frame($id); }, $results ); + } + } + + public static function find_one( $parameters = array() ) { + $results = Frame::find( $parameters, 1 ); + if ( ! sizeof( $results ) ) { + return; + } + return $results[0]; + } +} # end class +?> diff --git a/web/includes/Server.php b/web/includes/Server.php index e8402809c..dfce67eb8 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -1,28 +1,28 @@ $v) { - $this->{$k} = $v; - } - } else { - $this->{'Name'} = ''; - $this->{'Hostname'} = ''; - } +class Server { + public function __construct( $IdOrRow = NULL ) { + $row = NULL; + if ( $IdOrRow ) { + if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { + $row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) ); + if ( ! $row ) { + Error("Unable to load Server record for Id=" . $IdOrRow ); + } + } elseif ( is_array( $IdOrRow ) ) { + $row = $IdOrRow; + } + } # end if isset($IdOrRow) + if ( $row ) { + foreach ($row as $k => $v) { + $this->{$k} = $v; + } + } else { + $this->{'Name'} = ''; + $this->{'Hostname'} = ''; } + } public static function find_all() { $servers = array(); $result = dbQuery( 'SELECT * FROM Servers ORDER BY Name'); @@ -47,11 +47,38 @@ class Server { return $this->{'Name'}; } public function __call( $fn, array $args= NULL){ - if(isset($this->{$fn})){ - return $this->{$fn}; - #array_unshift($args, $this); - #call_user_func_array( $this->{$fn}, $args); - } + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); } + } + public static function find( $parameters = array(), $limit = NULL ) { + $sql = 'SELECT * FROM Servers'; + $values = array(); + if ( sizeof($parameters) ) { + $sql .= ' WHERE ' . implode( ' AND ', array_map( + function($v){ return $v.'=?'; }, + array_keys( $parameters ) + ) ); + $values = array_values( $parameters ); + } + if ( $limit ) { + $sql .= ' LIMIT ' . $limit; + } + $results = dbFetchAll( $sql, NULL, $values ); + if ( $results ) { + return array_map( function($id){ return new Server($id); }, $results ); + } + } + + public static function find_one( $parameters = array() ) { + $results = Server::find( $parameters, 1 ); + if ( ! sizeof( $results ) ) { + return; + } + return $results[0]; + } + } ?> diff --git a/web/includes/Storage.php b/web/includes/Storage.php new file mode 100644 index 000000000..546cb9cbe --- /dev/null +++ b/web/includes/Storage.php @@ -0,0 +1,51 @@ + $v) { + $this->{$k} = $v; + } + } else { + $this->{'Name'} = ''; + $this->{'Path'} = ''; + } + } + + public function Path() { + if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) { + return $this->{'Path'}; + } else if ( ! isset($this->{'Id'}) ) { + return ZM_DIR_EVENTS; + } + return $this->{'Name'}; + } + public function __call( $fn, array $args= NULL){ + if(isset($this->{$fn})){ + return $this->{$fn}; + #array_unshift($args, $this); + #call_user_func_array( $this->{$fn}, $args); + } + } + public static function find_all() { + $storage_areas = array(); + $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name'); + $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' ); + foreach ( $results as $row => $obj ) { + $storage_areas[] = $obj; + } + return $storage_areas; + } +} +?> From f55f979cc9c63201de7d3727265a319312dd00bc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 7 May 2016 09:30:03 -0400 Subject: [PATCH 17/49] use fully specified Config to simplify symbol tables --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 0e454d784..7366ada90 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -31,6 +31,8 @@ use warnings; require Exporter; require ZoneMinder::Base; require ZoneMinder::Database; +require ZoneMinder::Config; + our @ISA = qw(Exporter ZoneMinder::Base); @@ -87,8 +89,6 @@ our $VERSION = $ZoneMinder::Base::VERSION; # # ========================================================================== -use ZoneMinder::Config qw(:all); - use DBI; use Carp; use POSIX; @@ -152,7 +152,7 @@ sub new $this->{hasTerm} = -t STDERR; ( $this->{fileName} = $0 ) =~ s|^.*/||; - $this->{logPath} = $Config{ZM_PATH_LOGS}; + $this->{logPath} = $ZoneMinder::Config::Config{ZM_PATH_LOGS}; $this->{logFile} = $this->{logPath}."/".$this->{id}.".log"; $this->{trace} = 0; @@ -165,7 +165,7 @@ sub BEGIN { # Fake the config variables that are used in case they are not defined yet # Only really necessary to support upgrade from previous version - if ( !eval('defined($Config{ZM_LOG_DEBUG})') ) + if ( !eval('defined($ZoneMinder::Config::Config{ZM_LOG_DEBUG})') ) { no strict 'subs'; no strict 'refs'; @@ -223,7 +223,7 @@ sub initialise( @ ) } else { - $tempDatabaseLevel = $Config{ZM_LOG_LEVEL_DATABASE}; + $tempDatabaseLevel = $ZoneMinder::Config::Config{ZM_LOG_LEVEL_DATABASE}; } if ( defined($options{fileLevel}) ) { @@ -231,7 +231,7 @@ sub initialise( @ ) } else { - $tempFileLevel = $Config{ZM_LOG_LEVEL_FILE}; + $tempFileLevel = $ZoneMinder::Config::Config{ZM_LOG_LEVEL_FILE}; } if ( defined($options{syslogLevel}) ) { @@ -239,7 +239,7 @@ sub initialise( @ ) } else { - $tempSyslogLevel = $Config{ZM_LOG_LEVEL_SYSLOG}; + $tempSyslogLevel = $ZoneMinder::Config::Config{ZM_LOG_LEVEL_SYSLOG}; } if ( defined($ENV{'LOG_PRINT'}) ) @@ -255,9 +255,9 @@ sub initialise( @ ) $tempFileLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_FILE')) ); $tempSyslogLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG')) ); - if ( $Config{ZM_LOG_DEBUG} ) + if ( $ZoneMinder::Config::Config{ZM_LOG_DEBUG} ) { - foreach my $target ( split( /\|/, $Config{ZM_LOG_DEBUG_TARGET} ) ) + foreach my $target ( split( /\|/, $ZoneMinder::Config::Config{ZM_LOG_DEBUG_TARGET} ) ) { if ( $target eq $this->{id} || $target eq "_".$this->{id} @@ -266,12 +266,12 @@ sub initialise( @ ) || $target eq "" ) { - if ( $Config{ZM_LOG_DEBUG_LEVEL} > NOLOG ) + if ( $ZoneMinder::Config::Config{ZM_LOG_DEBUG_LEVEL} > NOLOG ) { - $tempLevel = $this->limit( $Config{ZM_LOG_DEBUG_LEVEL} ); - if ( $Config{ZM_LOG_DEBUG_FILE} ne "" ) + $tempLevel = $this->limit( $ZoneMinder::Config::Config{ZM_LOG_DEBUG_LEVEL} ); + if ( $ZoneMinder::Config::Config{ZM_LOG_DEBUG_FILE} ne "" ) { - $tempLogFile = $Config{ZM_LOG_DEBUG_FILE}; + $tempLogFile = $ZoneMinder::Config::Config{ZM_LOG_DEBUG_FILE}; $tempFileLevel = $tempLevel; } } @@ -466,9 +466,9 @@ sub databaseLevel { $databaseLevel = NOLOG; Error( "Unable to write log entries to DB, can't connect to database '" - .$Config{ZM_DB_NAME} + .$ZoneMinder::Config::Config{ZM_DB_NAME} ."' on host '" - .$Config{ZM_DB_HOST} + .$ZoneMinder::Config::Config{ZM_DB_HOST} ."'" ); } @@ -566,8 +566,8 @@ sub openFile { $LOGFILE->autoflush() if ( $this->{autoFlush} ); - my $webUid = (getpwnam( $Config{ZM_WEB_USER} ))[2]; - my $webGid = (getgrnam( $Config{ZM_WEB_GROUP} ))[2]; + my $webUid = (getpwnam( $ZoneMinder::Config::Config{ZM_WEB_USER} ))[2]; + my $webGid = (getgrnam( $ZoneMinder::Config::Config{ZM_WEB_GROUP} ))[2]; if ( $> == 0 ) { chown( $webUid, $webGid, $this->{logFile} ) From 6e32b5d26610f40dc5c260ef4271fca1054cd760 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 7 May 2016 09:34:04 -0400 Subject: [PATCH 18/49] Use fully specified COnfig hash to simplify Symbol tables --- scripts/ZoneMinder/lib/ZoneMinder/Database.pm | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm index fdea725fe..574c382f5 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm @@ -31,6 +31,7 @@ use DBI; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Config; our @ISA = qw(Exporter ZoneMinder::Base); @@ -65,7 +66,6 @@ our $VERSION = $ZoneMinder::Base::VERSION; # ========================================================================== use ZoneMinder::Logger qw(:all); -use ZoneMinder::Config qw(:all); use Carp; @@ -80,23 +80,23 @@ sub zmDbConnect } if ( !defined( $dbh ) ) { - my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); + my ( $host, $port ) = ( $ZoneMinder::Config::Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); if ( defined($port) ) { - $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} + $dbh = DBI->connect( "DBI:mysql:database=".$ZoneMinder::Config::Config{ZM_DB_NAME} .";host=".$host .";port=".$port - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} + , $ZoneMinder::Config::Config{ZM_DB_USER} + , $ZoneMinder::Config::Config{ZM_DB_PASS} ); } else { - $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$Config{ZM_DB_HOST} - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} + $dbh = DBI->connect( "DBI:mysql:database=".$ZoneMinder::Config::Config{ZM_DB_NAME} + .";host=".$ZoneMinder::Config::Config{ZM_DB_HOST} + , $ZoneMinder::Config::Config{ZM_DB_USER} + , $ZoneMinder::Config::Config{ZM_DB_PASS} ); } $dbh->trace( 0 ); From b444c8a6b41238e2557fef4258422bea41d6ec85 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 7 May 2016 09:34:45 -0400 Subject: [PATCH 19/49] Move the BEGIN from ZoneMinder to ZoneMinder/Base. --- scripts/ZoneMinder/lib/ZoneMinder.pm | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder.pm b/scripts/ZoneMinder/lib/ZoneMinder.pm index 37292a44d..63b7c8108 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder.pm @@ -81,12 +81,6 @@ our @EXPORT = ( @EXPORT_OK ); our $VERSION = $ZoneMinder::Base::VERSION; -BEGIN { - require ZoneMinder::Config; - require ZoneMinder::Database; - ZoneMinder::Config::zmConfigLoad(); - ZoneMinder::Database::zmDbConnect(); -} 1; __END__ From 3522c5796bd05e5a4475484ec277f274a71c16de Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 12:01:26 -0400 Subject: [PATCH 20/49] add BEGIN Back to ZoneMinder.pm --- scripts/ZoneMinder/lib/ZoneMinder.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder.pm b/scripts/ZoneMinder/lib/ZoneMinder.pm index 63b7c8108..6d8b3bfc8 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder.pm @@ -81,6 +81,10 @@ our @EXPORT = ( @EXPORT_OK ); our $VERSION = $ZoneMinder::Base::VERSION; +BEGIN { + ZoneMinder::Config::zmConfigLoad(); + ZoneMinder::Database::zmDbConnect(); +} 1; __END__ From b33e35bda7f1bedbc795fc320d2a65cc8460edab Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 12:14:59 -0400 Subject: [PATCH 21/49] move the require to the top --- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 03f05d0e8..54cc8c3f3 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -30,6 +30,7 @@ use warnings; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -83,7 +84,6 @@ sub zmConfigLoad { } close( $CONFIG ); - require ZoneMinder::Database; my $dbh = ZoneMinder::Database::zmDbConnect() or croak( "Can't connect to db" ); my $sql = 'select * from Config'; my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); From 08bf97fe85c8f6de5b44234147cc87818b254bed Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 12:44:41 -0400 Subject: [PATCH 22/49] Add a config entry for ZM_LD_PRELOAD --- scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index fc4143d8a..01d4b534c 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -1709,6 +1709,16 @@ our @options = type => $types{boolean}, category => "config", }, + { + name => 'ZM_LD_PRELOAD', + default => '', + description => "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", From 605edfd6d0d80c688ec3b8e247d5ef973ab34b6a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 12:46:26 -0400 Subject: [PATCH 23/49] add ENV{LD_PRELOAD} setting --- scripts/zmdc.pl.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in index 36d5e922a..730af9995 100644 --- a/scripts/zmdc.pl.in +++ b/scripts/zmdc.pl.in @@ -75,6 +75,10 @@ $| = 1; $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +if ( $Config{ZM_LD_PRELOAD} ) { + Debug("Adding ENV{LD_PRELOAD} = $Config{ZM_LD_PRELOAD}"); + $ENV{LD_PRELOAD} = $Config{ZM_LD_PRELOAD}; +} delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my @daemons = ( From 5566d1881df20b0283ae73f0a68e3304deb2635e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 21:34:12 -0400 Subject: [PATCH 24/49] add perl dbd mysql to build depends. Seems to need it. --- distros/ubuntu1204/control | 1 + 1 file changed, 1 insertion(+) diff --git a/distros/ubuntu1204/control b/distros/ubuntu1204/control index 6368d9417..3fedf7129 100644 --- a/distros/ubuntu1204/control +++ b/distros/ubuntu1204/control @@ -16,6 +16,7 @@ Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh ,libpolkit-gobject-1-dev ,libv4l-dev (>= 0.8.3) [!hurd-any] ,libvlc-dev + ,libdbd-mysql-perl # Unbundled (dh_linktree): ,libjs-jquery ,libjs-mootools From 4d20d35f8d46fc2db6b51e5f30778e17e0a13f11 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 May 2016 08:43:38 -0400 Subject: [PATCH 25/49] add back missing depends for perl modules which are needed both for building and installing --- distros/ubuntu1204/control | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/distros/ubuntu1204/control b/distros/ubuntu1204/control index 3fedf7129..0791622ed 100644 --- a/distros/ubuntu1204/control +++ b/distros/ubuntu1204/control @@ -5,18 +5,22 @@ Maintainer: Dmitry Smirnov Uploaders: Vagrant Cascadian Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh-linktree ,cmake - ,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev + ,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev ,libbz2-dev ,libgcrypt-dev ,libcurl4-gnutls-dev ,libgnutls-openssl-dev - ,libjpeg8-dev|libjpeg9-dev|libjpeg62-turbo-dev, + ,libjpeg8-dev|libjpeg9-dev|libjpeg62-turbo-dev, ,libmysqlclient-dev ,libpcre3-dev ,libpolkit-gobject-1-dev ,libv4l-dev (>= 0.8.3) [!hurd-any] ,libvlc-dev + ,libdate-manip-perl ,libdbd-mysql-perl + ,libphp-serialization-perl + ,libsys-mmap-perl [!hurd-any] + ,libwww-perl # Unbundled (dh_linktree): ,libjs-jquery ,libjs-mootools From a5ba4759bf27108aed334f1d7a0b6f5fa30fd5fe Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 May 2016 10:54:40 -0400 Subject: [PATCH 26/49] fix new config entry --- scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 01d4b534c..610d2432d 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -1712,7 +1712,8 @@ our @options = { name => 'ZM_LD_PRELOAD', default => '', - description => "Some older cameras require the use of the v4l1 compat + 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."), From 2888142e682bbc9950535d7e5aaef2cd20cda38d Mon Sep 17 00:00:00 2001 From: arjunrc Date: Tue, 10 May 2016 16:55:43 -0400 Subject: [PATCH 27/49] added status command to retrieve alarmed status of monitor in addition to on/of --- web/api/app/Controller/MonitorsController.php | 79 ++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 9ab7461f9..d87b115e8 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -97,7 +97,7 @@ public function beforeFilter() { if ($this->Session->Read('systemPermission') != 'Edit') { - throw new UnauthotizedException(__('Insufficient privileges')); + throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -183,6 +183,83 @@ 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'; + break; + case "off": + $q = "-c"; + break; + case "status": + $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 -v -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']; From 8d5f2a8e5dbc946fb652cb530ded953a766a5192 Mon Sep 17 00:00:00 2001 From: arjunrc Date: Tue, 10 May 2016 19:17:09 -0400 Subject: [PATCH 28/49] added iconnor's change back --- web/api/app/Controller/MonitorsController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index d87b115e8..63849af69 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -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' ); } /** From af3cae578e501694e7fc2e15bf668736055a3f3d Mon Sep 17 00:00:00 2001 From: arjunrc Date: Tue, 10 May 2016 20:07:28 -0400 Subject: [PATCH 29/49] fixed verbose handling bug for status command on zmu --- web/api/app/Controller/MonitorsController.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 63849af69..cda5081d7 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -138,8 +138,7 @@ public function beforeFilter() { '_serialize' => array('message') )); // - restart this monitor after change - // We don't pass the request data as the monitor object because it may be a subset of the full monitor array - $this->daemonControl( $this->Monitor->id, 'restart' ); + $this->daemonControl($this->Monitor->id, 'restart', $this->request->data); } /** @@ -205,11 +204,14 @@ public function beforeFilter() { { 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; } @@ -250,7 +252,7 @@ public function beforeFilter() { } } - $shellcmd = escapeshellcmd("$zm_path_bin/zmu -v -m$id $q $auth"); + $shellcmd = escapeshellcmd("$zm_path_bin/zmu $verbose -m$id $q $auth"); $status = exec ($shellcmd); $this->set(array( From b513bcef821a0423eee2cffe7073b8c58a36a9f1 Mon Sep 17 00:00:00 2001 From: arjunrc Date: Tue, 10 May 2016 20:09:41 -0400 Subject: [PATCH 30/49] icon's gonna kill me --- web/api/app/Controller/MonitorsController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index cda5081d7..893410ce8 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -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' ); } /** From 1530096560e9f48e003efcaebcdcdea983b5391a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 12 May 2016 10:17:41 -0400 Subject: [PATCH 31/49] whitespace/google code style --- web/includes/functions.php | 4030 ++++++++++++++++-------------------- 1 file changed, 1814 insertions(+), 2216 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 9a8264548..314806105 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -19,2501 +19,2099 @@ // // Compatibility functions -if ( version_compare( phpversion(), "4.3.0", "<") ) -{ - function ob_get_clean() - { - $buffer = ob_get_contents(); - ob_end_clean(); - return( $buffer ); - } +if ( version_compare( phpversion(), "4.3.0", "<") ) { + function ob_get_clean() { + $buffer = ob_get_contents(); + ob_end_clean(); + return( $buffer ); + } } -function userLogin( $username, $password="", $passwordHashed=false ) -{ - global $user, $cookies; +function userLogin( $username, $password="", $passwordHashed=false ) { + global $user, $cookies; - $sql = "select * from Users where Enabled = 1"; - $sql_values = NULL; - if ( ZM_AUTH_TYPE == "builtin" ) - { - if ( $passwordHashed ) { - $sql .= " AND Username=? AND Password=?"; - } else { - $sql .= " AND Username=? AND Password=password(?)"; - } - $sql_values = array( $username, $password ); + $sql = "select * from Users where Enabled = 1"; + $sql_values = NULL; + if ( ZM_AUTH_TYPE == "builtin" ) { + if ( $passwordHashed ) { + $sql .= " AND Username=? AND Password=?"; } else { - $sql .= " AND Username = ?"; - $sql_values = array( $username ); + $sql .= " AND Username=? AND Password=password(?)"; } - $_SESSION['username'] = $username; - if ( ZM_AUTH_RELAY == "plain" ) - { - // Need to save this in session - $_SESSION['password'] = $password; + $sql_values = array( $username, $password ); + } else { + $sql .= " AND Username = ?"; + $sql_values = array( $username ); + } + $_SESSION['username'] = $username; + if ( ZM_AUTH_RELAY == "plain" ) { + // Need to save this in session + $_SESSION['password'] = $password; + } + $_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking + if ( $dbUser = dbFetchOne( $sql, NULL, $sql_values ) ) { + Info( "Login successful for user \"$username\"" ); + $_SESSION['user'] = $user = $dbUser; + if ( ZM_AUTH_TYPE == "builtin" ) { + $_SESSION['passwordHash'] = $user['Password']; } - $_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking - if ( $dbUser = dbFetchOne( $sql, NULL, $sql_values ) ) - { - Info( "Login successful for user \"$username\"" ); - $_SESSION['user'] = $user = $dbUser; - if ( ZM_AUTH_TYPE == "builtin" ) - { - $_SESSION['passwordHash'] = $user['Password']; - } - } - else - { - Warning( "Login denied for user \"$username\"" ); - unset( $user ); - } - if ( $cookies ) - session_write_close(); -} - -function userLogout() -{ - global $user; - $username = $user['Username']; - - Info( "User \"$username\" logged out" ); - - unset( $_SESSION['user'] ); + } else { + Warning( "Login denied for user \"$username\"" ); unset( $user ); - - session_destroy(); + } + if ( $cookies ) + session_write_close(); } -function noCacheHeaders() -{ - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past - header("Last-Modified: ".gmdate( "D, d M Y H:i:s" )." GMT"); // always modified - header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); // HTTP/1.0 +function userLogout() { + global $user; + $username = $user['Username']; + + Info( "User \"$username\" logged out" ); + + unset( $_SESSION['user'] ); + unset( $user ); + + session_destroy(); +} + +function noCacheHeaders() { + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past + header("Last-Modified: ".gmdate( "D, d M Y H:i:s" )." GMT"); // always modified + header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); // HTTP/1.0 } function CORSHeaders() { - if ( isset( $_SERVER['HTTP_ORIGIN'] ) ) { + if ( isset( $_SERVER['HTTP_ORIGIN'] ) ) { - # The following is left for future reference/use. - $valid = false; - $servers = dbFetchAll( 'SELECT * FROM Servers' ); - if ( sizeof($servers) <= 1 ) { - # Only need CORSHeaders in the event that there are multiple servers in use. - return; - } - foreach( dbFetchAll( 'SELECT * FROM Servers' ) as $row ) { - $Server = new Server( $row ); - if ( $_SERVER['HTTP_ORIGIN'] == $Server->Url() ) { - $valid = true; - header("Access-Control-Allow-Origin: " . $Server->Url() ); - header("Access-Control-Allow-Headers: x-requested-with,x-request"); - } - } - if ( ! $valid ) { - Warning( $_SERVER['HTTP_ORIGIN'] . " is not found in servers list." ); - } - } +# The following is left for future reference/use. + $valid = false; + $servers = dbFetchAll( 'SELECT * FROM Servers' ); + if ( sizeof($servers) <= 1 ) { +# Only need CORSHeaders in the event that there are multiple servers in use. + return; + } + foreach( dbFetchAll( 'SELECT * FROM Servers' ) as $row ) { + $Server = new Server( $row ); + if ( $_SERVER['HTTP_ORIGIN'] == $Server->Url() ) { + $valid = true; + header("Access-Control-Allow-Origin: " . $Server->Url() ); + header("Access-Control-Allow-Headers: x-requested-with,x-request"); + } + } + if ( ! $valid ) { + Warning( $_SERVER['HTTP_ORIGIN'] . " is not found in servers list." ); + } + } } -function getAuthUser( $auth ) -{ - if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" && !empty($auth) ) - { +function getAuthUser( $auth ) { + if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" && !empty($auth) ) { + $remoteAddr = ""; + if ( ZM_AUTH_HASH_IPS ) { + $remoteAddr = $_SERVER['REMOTE_ADDR']; + if ( !$remoteAddr ) { + Error( "Can't determine remote address for authentication, using empty string" ); $remoteAddr = ""; - if ( ZM_AUTH_HASH_IPS ) - { - $remoteAddr = $_SERVER['REMOTE_ADDR']; - if ( !$remoteAddr ) - { - Error( "Can't determine remote address for authentication, using empty string" ); - $remoteAddr = ""; - } - } - - $sql = "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1"; - foreach ( dbFetchAll( $sql ) as $user ) - { - $now = time(); - for ( $i = 0; $i < 2; $i++, $now -= (60*60) ) // Try for last two hours - { - $time = localtime( $now ); - $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5]; - $authHash = md5( $authKey ); - - if ( $auth == $authHash ) - { - return( $user ); - } - } - } + } } - Error( "Unable to authenticate user from auth hash '$auth'" ); - return( false ); + + $sql = "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1"; + foreach ( dbFetchAll( $sql ) as $user ) { + $now = time(); + for ( $i = 0; $i < 2; $i++, $now -= (60*60) ) { // Try for last two hours + $time = localtime( $now ); + $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5]; + $authHash = md5( $authKey ); + + if ( $auth == $authHash ) { + return( $user ); + } + } + } + } + Error( "Unable to authenticate user from auth hash '$auth'" ); + return( false ); } -function generateAuthHash( $useRemoteAddr ) -{ - if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) - { - $time = localtime(); - if ( $useRemoteAddr ) - { - $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$time[2].$time[3].$time[4].$time[5]; - } - else - { - $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$time[2].$time[3].$time[4].$time[5]; - } - $auth = md5( $authKey ); +function generateAuthHash( $useRemoteAddr ) { + if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == "hashed" ) { + $time = localtime(); + if ( $useRemoteAddr ) { + $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$time[2].$time[3].$time[4].$time[5]; + } else { + $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$time[2].$time[3].$time[4].$time[5]; } - else - { - $auth = ""; - } - return( $auth ); + $auth = md5( $authKey ); + } else { + $auth = ""; + } + return( $auth ); } -function getStreamSrc( $args, $querySep='&' ) -{ - $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; +function getStreamSrc( $args, $querySep='&' ) { + $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; - if ( ZM_OPT_USE_AUTH ) - { - if ( ZM_AUTH_RELAY == "hashed" ) - { - $args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS ); - } - elseif ( ZM_AUTH_RELAY == "plain" ) - { - $args[] = "user=".$_SESSION['username']; - $args[] = "pass=".$_SESSION['password']; - } - elseif ( ZM_AUTH_RELAY == "none" ) - { - $args[] = "user=".$_SESSION['username']; - } - } - if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) - { - $args[] = "connkey=".$GLOBALS['connkey']; - } - if ( ZM_RAND_STREAM ) - { - $args[] = "rand=".time(); + if ( ZM_OPT_USE_AUTH ) { + if ( ZM_AUTH_RELAY == "hashed" ) { + $args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS ); + } elseif ( ZM_AUTH_RELAY == "plain" ) { + $args[] = "user=".$_SESSION['username']; + $args[] = "pass=".$_SESSION['password']; + } elseif ( ZM_AUTH_RELAY == "none" ) { + $args[] = "user=".$_SESSION['username']; } + } + if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) { + $args[] = "connkey=".$GLOBALS['connkey']; + } + if ( ZM_RAND_STREAM ) { + $args[] = "rand=".time(); + } - if ( count($args) ) - { - $streamSrc .= "?".join( $querySep, $args ); - } + if ( count($args) ) { + $streamSrc .= "?".join( $querySep, $args ); + } - return( $streamSrc ); + return( $streamSrc ); } -function getMimeType( $file ) -{ - if ( function_exists('mime_content_type') ) - { - return( mime_content_type( $file ) ); - } - elseif ( function_exists('finfo_file') ) - { - $finfo = finfo_open( FILEINFO_MIME ); - $mimeType = finfo_file( $finfo, $file ); - finfo_close($finfo); - return( $mimeType ); - } - return( trim( exec( 'file -bi '.escapeshellarg( $file ).' 2>/dev/null' ) ) ); +function getMimeType( $file ) { + if ( function_exists('mime_content_type') ) { + return( mime_content_type( $file ) ); + } elseif ( function_exists('finfo_file') ) { + $finfo = finfo_open( FILEINFO_MIME ); + $mimeType = finfo_file( $finfo, $file ); + finfo_close($finfo); + return( $mimeType ); + } + return( trim( exec( 'file -bi '.escapeshellarg( $file ).' 2>/dev/null' ) ) ); } -function outputVideoStream( $id, $src, $width, $height, $format, $title="" ) -{ - if ( file_exists( $src ) ) - $mimeType = getMimeType( $src ); - else - { - switch( $format ) +function outputVideoStream( $id, $src, $width, $height, $format, $title="" ) { + if ( file_exists( $src ) ) { + $mimeType = getMimeType( $src ); + } else { + switch( $format ) { + case 'asf' : + $mimeType = "video/x-ms-asf"; + break; + case 'avi' : + case 'wmv' : + $mimeType = "video/x-msvideo"; + break; + case 'mov' : + $mimeType = "video/quicktime"; + break; + case 'mpg' : + case 'mpeg' : + $mimeType = "video/mpeg"; + break; + case 'swf' : + $mimeType = "application/x-shockwave-flash"; + break; + case '3gp' : + $mimeType = "video/3gpp"; + break; + default : + $mimeType = "video/$format"; + break; + } + } + if ( !$mimeType || ($mimeType == 'application/octet-stream') ) + $mimeType = 'video/'.$format; + $objectTag = false; + if ( ZM_WEB_USE_OBJECT_TAGS ) { + switch( $mimeType ) { + case "video/x-ms-asf" : + case "video/x-msvideo" : + case "video/mp4" : { - case 'asf' : - $mimeType = "video/x-ms-asf"; - break; - case 'avi' : - case 'wmv' : - $mimeType = "video/x-msvideo"; - break; - case 'mov' : - $mimeType = "video/quicktime"; - break; - case 'mpg' : - case 'mpeg' : - $mimeType = "video/mpeg"; - break; - case 'swf' : - $mimeType = "application/x-shockwave-flash"; - break; - case '3gp' : - $mimeType = "video/3gpp"; - break; - default : - $mimeType = "video/$format"; - break; + if ( isWindows() ) { + ?> + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - -src="" -name="" -width="" -height="" -autostart="1" -autoplay="1" -showcontrols="0" -controller="0"> - - + + src="" + name="" + width="" + height="" + autostart="1" + autoplay="1" + showcontrols="0" + controller="0"> + + -