From 4be668f838b59614d204c963ffec5953bdda1786 Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Sun, 6 Nov 2016 08:03:43 -0600 Subject: [PATCH 01/12] Add HikVision ptz control sciprt --- db/zm_create.sql.in | 1 + .../lib/ZoneMinder/Control/HikVision.pm | 411 ++++++++++++++++++ .../lib/ZoneMinder/Control/IPCC7210W.pm | 0 .../lib/ZoneMinder/Control/WanscamHW0025.pm | 0 4 files changed, 412 insertions(+) create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/HikVision.pm mode change 100755 => 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/IPCC7210W.pm mode change 100755 => 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/WanscamHW0025.pm diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 0d6c853c9..24c73c8eb 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -595,6 +595,7 @@ INSERT INTO `Controls` VALUES (NULL,'IPCC 7210W','Libvlc','IPCC7210W', 1, 1, 1, INSERT INTO `Controls` VALUES (NULL,'Vivotek ePTZ','Remote','Vivotek_ePTZ',0,0,1,1,0,0,0,1,0,0,0,0,1,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,5,0,0,1,0,0,0,0,1,0,5,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Netcat ONVIF','Ffmpeg','Netcat',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,100,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,100,5,5,0,0,0,1,255,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Keekoon','Remote','Keekoon', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `Controls` VALUES (NULL,'HikVision','Local','',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,100,0,0,1,0,0,0,0,1,1,100,1,0,0,0); -- -- Add some monitor preset values diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/HikVision.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/HikVision.pm new file mode 100644 index 000000000..2c665b4ad --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/HikVision.pm @@ -0,0 +1,411 @@ +# ========================================================================== +# +# ZoneMinder HikVision Control Protocol Module +# Copyright (C) 2016 Terry Sanders +# +# 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 an implementation of the HikVision ISAPI camera control +# protocol +# +package ZoneMinder::Control::HikVision; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +# ========================================================================== +# +# HiKVision ISAPI Control Protocol +# +# Set the following: +# ControlAddress: username:password@camera_webaddress:port +# ControlDevice: IP Camera Model +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Time::HiRes qw( usleep ); + +use LWP::UserAgent; +use HTTP::Cookies; + +my $ChannelID = 1; # Usually... +my $DefaultFocusSpeed = 50; # Should be between 1 and 100 +my $DefaultIrisSpeed = 50; # Should be between 1 and 100 + +sub new { + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD { + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} +sub open { + my $self = shift; + $self->loadMonitor(); + # + # Create a UserAgent for the requests + # + $self->{UA} = LWP::UserAgent->new(); + $self->{UA}->cookie_jar( {} ); + # + # Extract the username/password host/port from ControlAddress + # + my ($user,$pass,$host,$port); + if( $self->{Monitor}{ControlAddress} =~ /^([^:]+):([^@]+)@(.+)/ ) { # user:pass@host... + $user = $1; + $pass = $2; + $host = $3; + } + elsif( $self->{Monitor}{ControlAddress} =~ /^([^@]+)@(.+)/ ) { # user@host... + $user = $1; + $host = $2; + } + else { # Just a host + $host = $self->{Monitor}{ControlAddress}; + } + # Check if it is a host and port or just a host + if( $host =~ /([^:]+):(.+)/ ) { + $host = $1; + $port = $2; + } + else { + $port = 80; + } + # Save the credentials + if( defined($user) ) { + $self->{UA}->credentials( "$host:$port", $self->{Monitor}{ControlDevice}, $user, $pass ); + } + # Save the base url + $self->{BaseURL} = "http://$host:$port"; +} +sub PutCmd { + my $self = shift; + my $cmd = shift; + my $content = shift; + my $req = HTTP::Request->new(PUT => "$self->{BaseURL}/$cmd"); + if(defined($content)) { + $req->content_type("application/x-www-form-urlencoded; charset=UTF-8"); + $req->content('' . "\n" . $content); + } + my $res = $self->{UA}->request($req); + unless( $res->is_success ) { + # + # The camera timeouts connections at short intervals. When this + # happens the user agent connects again and uses the same auth tokens. + # The camera rejects this and asks for another token but the UserAgent + # just gives up. Because of this I try the request again and it should + # succeed the second time if the credentials are correct. + # + if($res->code == 401) { + $res = $self->{UA}->request($req); + unless( $res->is_success ) { + # + # It has failed authentication. The odds are + # that the user has set some paramater incorrectly + # so check the realm against the ControlDevice + # entry and send a message if different + # + my $auth = $res->headers->www_authenticate; + foreach (split(/\s*,\s*/,$auth)) { + if( $_ =~ /^realm\s*=\s*"([^"]+)"/i ) { + if( $self->{Monitor}{ControlDevice} ne $1 ) { + Info "Control Device appears to be incorrect."; + Info "Control Device should be set to \"$1\"."; + Info "Control Device currently set to \"$self->{Monitor}{ControlDevice}\"."; + } + } + } + # + # Check for username/password + # + if( $self->{Monitor}{ControlAddress} =~ /.+:(.+)@.+/ ) { + Info "Check username/password is correct"; + } elsif ( $self->{Monitor}{ControlAddress} =~ /^[^:]+@.+/ ) { + Info "No password in Control Address. Should there be one?"; + } elsif ( $self->{Monitor}{ControlAddress} =~ /^:.+@.+/ ) { + Info "Password but no username in Control Address."; + } else { + Info "Missing username and password in Control Address."; + } + Fatal $res->status_line; + } + } + else { + Fatal $res->status_line; + } + } +} +# +# The move continuous functions all call moveVector +# with the direction to move in. This includes zoom +# +sub moveVector { + my $self = shift; + my $pandirection = shift; + my $tiltdirection = shift; + my $zoomdirection = shift; + my $params = shift; + my $command; # The ISAPI/PTZ command + + # Calculate autostop time + my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; + # Change from microseconds to milliseconds + $duration = int($duration/1000); + my $momentxml; + if( $duration ) { + $momentxml = "$duration"; + $command = "ISAPI/PTZCtrl/channels/$ChannelID/momentary"; + } + else { + $momentxml = ""; + $command = "ISAPI/PTZCtrl/channels/$ChannelID/continuous"; + } + # Calculate movement speeds + my $x = $pandirection * $self->getParam( $params, 'panspeed', 0 ); + my $y = $tiltdirection * $self->getParam( $params, 'tiltspeed', 0 ); + my $z = $zoomdirection * $self->getParam( $params, 'speed', 0 ); + # Create the XML + my $xml = "$x$y$z$momentxml"; + # Send it to the camera + $self->PutCmd($command,$xml); +} +sub moveStop { $_[0]->moveVector( 0, 0, 0, splice(@_,1)); } +sub moveConUp { $_[0]->moveVector( 0, 1, 0, splice(@_,1)); } +sub moveConUpRight { $_[0]->moveVector( 1, 1, 0, splice(@_,1)); } +sub moveConRight { $_[0]->moveVector( 1, 0, 0, splice(@_,1)); } +sub moveConDownRight { $_[0]->moveVector( 1, -1, 0, splice(@_,1)); } +sub moveConDown { $_[0]->moveVector( 0, -1, 0, splice(@_,1)); } +sub moveConDownLeft { $_[0]->moveVector( -1, -1, 0, splice(@_,1)); } +sub moveConLeft { $_[0]->moveVector( -1, 0, 0, splice(@_,1)); } +sub moveConUpLeft { $_[0]->moveVector( -1, 1, 0, splice(@_,1)); } +sub zoomConTele { $_[0]->moveVector( 0, 0, 1, splice(@_,1)); } +sub zoomConWide { $_[0]->moveVector( 0, 0,-1, splice(@_,1)); } +# +# Presets including Home set and clear +# +sub presetGoto { + my $self = shift; + my $params = shift; + my $preset = $self->getParam($params,'preset'); + $self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/presets/$preset/goto"); +} +sub presetSet { + my $self = shift; + my $params = shift; + my $preset = $self->getParam($params,'preset'); + my $xml = "$preset"; + $self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/presets/$preset",$xml); +} +sub presetHome { + my $self = shift; + my $params = shift; + $self->PutCmd("ISAPI/PTZCtrl/channels/$ChannelID/homeposition/goto"); +} +# +# Focus controls all call Focus with a +/- speed +# +sub Focus { + my $self = shift; + my $speed = shift; + my $xml = "$speed"; + $self->PutCmd("ISAPI/System/Video/inputs/channels/$ChannelID/focus",$xml); +} +sub focusConNear { + my $self = shift; + my $params = shift; + + # Calculate autostop time + my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; + # Get the focus speed + my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); + $self->Focus(-$speed); + if($duration) { + usleep($duration); + $self->moveStop($params); + } +} +sub Near { + my $self = shift; + my $params = shift; + $self->Focus(-$DefaultFocusSpeed); +} +sub focusAbsNear { + my $self = shift; + my $params = shift; + + # Get the focus speed + my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); + $self->Focus(-$speed); +} +sub focusRelNear { + my $self = shift; + my $params = shift; + # Get the focus speed + my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); + $self->Focus(-$speed); +} +sub focusConFar { + my $self = shift; + my $params = shift; + + # Calculate autostop time + my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; + # Get the focus speed + my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); + $self->Focus($speed); + if($duration) { + usleep($duration); + $self->moveStop($params); + } +} +sub Far { + my $self = shift; + my $params = shift; + $self->Focus($DefaultFocusSpeed); +} +sub focusAbsFar { + my $self = shift; + my $params = shift; + + # Get the focus speed + my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); + $self->Focus($speed); +} +sub focusRelFar { + my $self = shift; + my $params = shift; + + # Get the focus speed + my $speed = $self->getParam( $params, 'speed', $DefaultFocusSpeed ); + $self->Focus($speed); +} +# +# Iris controls all call Iris with a +/- speed +# +sub Iris { + my $self = shift; + my $speed = shift; + + my $xml = "$speed"; + $self->PutCmd("ISAPI/System/Video/inputs/channels/$ChannelID/iris",$xml); +} +sub irisConClose { + my $self = shift; + my $params = shift; + + # Calculate autostop time + my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; + # Get the iris speed + my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); + $self->Iris(-$speed); + if($duration) { + usleep($duration); + $self->moveStop($params); + } +} +sub Close { + my $self = shift; + my $params = shift; + + $self->Iris(-$DefaultIrisSpeed); +} +sub irisAbsClose { + my $self = shift; + my $params = shift; + + # Get the iris speed + my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); + $self->Iris(-$speed); +} +sub irisRelClose { + my $self = shift; + my $params = shift; + + # Get the iris speed + my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); + $self->Iris(-$speed); +} +sub irisConOpen { + my $self = shift; + my $params = shift; + + # Calculate autostop time + my $duration = $self->getParam( $params, 'autostop', 0 ) * $self->{Monitor}{AutoStopTimeout}; + # Get the iris speed + my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); + $self->Iris($speed); + if($duration) { + usleep($duration); + $self->moveStop($params); + } +} +sub Open { + my $self = shift; + my $params = shift; + + $self->Iris($DefaultIrisSpeed); +} +sub irisAbsOpen { + my $self = shift; + my $params = shift; + + # Get the iris speed + my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); + $self->Iris($speed); +} +sub irisRelOpen { + my $self = shift; + my $params = shift; + + # Get the iris speed + my $speed = $self->getParam( $params, 'speed', $DefaultIrisSpeed ); + $self->Iris($speed); +} +# +# reset (reboot) the device +# +sub reset { + my $self = shift; + + $self->PutCmd("ISAPI/System/reboot"); +} + +1; + diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCC7210W.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCC7210W.pm old mode 100755 new mode 100644 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/WanscamHW0025.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/WanscamHW0025.pm old mode 100755 new mode 100644 From 09fae00c13c089c79baccb7663b230ac8a8755d5 Mon Sep 17 00:00:00 2001 From: Stefan Lindblom Date: Mon, 2 Jan 2017 09:09:53 +0100 Subject: [PATCH 02/12] Add MonitorPreset for Qihan IP cameras via RTSP --- db/zm_create.sql.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 0d6c853c9..fc1a8c446 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -667,6 +667,8 @@ INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI9821W FFMPEG H.264','Ffmpeg',N INSERT INTO MonitorPresets VALUES (NULL,'Loftek Sentinel PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,'','80','/videostream.cgi?user=&pwd=&resolution=32&rate=11',NULL,640,480,4,NULL,1,'13','',':@',100,100); INSERT INTO MonitorPresets VALUES (NULL,'Airlink 777W PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,':@','80','/cgi/mjpg/mjpg.cgi',NULL,640,480,4,NULL,1,'7','',':@',100,100); INSERT INTO MonitorPresets VALUES (NULL,'SunEyes SP-P1802SWPTZ','Libvlc','/dev/video','0',255,'','rtpMulti','','80','rtsp://:554/11','',1920,1080,0,0.00,1,'16','-speed=64',':',100,33); +INSERT INTO MonitorPresets VALUES (NULL,'Qihan IP, 1280x720, RTP/RTSP','Remote','rtsp','rtpRtsp',255,'rtsp','rtpRtsp','',554,'/tcp_live/ch0_0',NULL,1280,720,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES (NULL,'Qihan IP, 1920x1080, RTP/RTSP','Remote','rtsp','rtpRtsp',255,'rtsp','rtpRtsp','',554,'/tcp_live/ch0_0',NULL,1920,1080,3,NULL,0,NULL,NULL,NULL,100,100); -- -- Add some zone preset values From b4f537c5d39bf985282ec940d66e793cea56a8f4 Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Tue, 3 Jan 2017 13:12:12 -0600 Subject: [PATCH 03/12] rpm build tweaks based on rpmfusion feedback --- distros/redhat/CMakeLists.txt | 2 -- distros/redhat/nginx/zoneminder.service.in | 3 +++ distros/redhat/systemd/zoneminder.service.in | 3 +++ distros/redhat/zoneminder.spec | 9 +++++---- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index df3edf7d9..f8acef552 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -49,10 +49,8 @@ endif("${unzip_jsc}" STREQUAL "") file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp) # Install the empty folders -#install(DIRECTORY run DESTINATION /var DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_WRITE GROUP_READ GROUP_EXECUTE WORLD_WRITE WORLD_READ WORLD_EXECUTE) install(DIRECTORY sock swap DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY zoneminder DESTINATION /var/log DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) -install(DIRECTORY zoneminder DESTINATION /run DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY zoneminder-upload DESTINATION /var/spool DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY events images temp DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/distros/redhat/nginx/zoneminder.service.in b/distros/redhat/nginx/zoneminder.service.in index da569423d..7e2e36585 100644 --- a/distros/redhat/nginx/zoneminder.service.in +++ b/distros/redhat/nginx/zoneminder.service.in @@ -8,12 +8,15 @@ Requires=mariadb.service nginx.service php-fpm.service fcgiwrap.service [Service] User=@WEB_USER@ +Group=@WEB_GROUP@ Type=forking ExecStart=@BINDIR@/zmpkg.pl start ExecReload=@BINDIR@/zmpkg.pl restart ExecStop=@BINDIR@/zmpkg.pl stop PIDFile=@ZM_RUNDIR@/zm.pid Environment=TZ=/etc/localtime +RuntimeDirectory=zoneminder +RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target diff --git a/distros/redhat/systemd/zoneminder.service.in b/distros/redhat/systemd/zoneminder.service.in index 030ca8065..2234af036 100644 --- a/distros/redhat/systemd/zoneminder.service.in +++ b/distros/redhat/systemd/zoneminder.service.in @@ -7,12 +7,15 @@ Requires=mariadb.service httpd.service [Service] User=@WEB_USER@ +Group=@WEB_GROUP@ Type=forking ExecStart=@BINDIR@/zmpkg.pl start ExecReload=@BINDIR@/zmpkg.pl restart ExecStop=@BINDIR@/zmpkg.pl stop PIDFile=@ZM_RUNDIR@/zm.pid Environment=TZ=/etc/localtime +RuntimeDirectory=zoneminder +RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 58a5a1a44..ad8615d06 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -5,10 +5,10 @@ %{!?make_build: %global make_build %{__make} %{?_smp_mflags} } %if "%{zmuid_final}" == "nginx" - %global with_nginx 1 - %global wwwconfdir /etc/nginx/default.d +%global with_nginx 1 +%global wwwconfdir /etc/nginx/default.d %else - %global wwwconfdir /etc/httpd/conf.d +%global wwwconfdir /etc/httpd/conf.d %endif %global sslcert %{_sysconfdir}/pki/tls/certs/localhost.crt @@ -50,6 +50,7 @@ Source: ZoneMinder-%{version}.tar.gz %{?with_init_systemd:BuildRequires: systemd-devel mariadb-devel perl-podlators} %{?with_init_sysv:BuildRequires: mysql-devel} BuildRequires: cmake >= 2.8.7 +BuildRequires: perl-generators BuildRequires: gnutls-devel bzip2-devel BuildRequires: pcre-devel libjpeg-turbo-devel BuildRequires: perl(Archive::Tar) perl(Archive::Zip) @@ -301,7 +302,7 @@ rm -rf %{_docdir}/%{name}-%{version} %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/temp %dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/log/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/spool/zoneminder-upload -%dir %attr(755,%{zmuid_final},%{zmgid_final}) %ghost /run/zoneminder +%dir %attr(755,%{zmuid_final},%{zmgid_final}) %ghost /var/run/zoneminder %changelog * Wed Dec 28 2016 Andrew Bauer - 1.30.1-2 From 7e7ef464206e090697274a281499b7b148c55074 Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Tue, 3 Jan 2017 16:42:12 -0600 Subject: [PATCH 04/12] rpm packaging - remove rundir from tmpfiles.d --- distros/redhat/nginx/zoneminder.tmpfiles.in | 1 - distros/redhat/systemd/zoneminder.tmpfiles.in | 1 - 2 files changed, 2 deletions(-) diff --git a/distros/redhat/nginx/zoneminder.tmpfiles.in b/distros/redhat/nginx/zoneminder.tmpfiles.in index d92ceaafd..8040a7877 100644 --- a/distros/redhat/nginx/zoneminder.tmpfiles.in +++ b/distros/redhat/nginx/zoneminder.tmpfiles.in @@ -1,4 +1,3 @@ -D @ZM_RUNDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_TMPDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D /var/lib/php/session 770 root @WEB_GROUP@ diff --git a/distros/redhat/systemd/zoneminder.tmpfiles.in b/distros/redhat/systemd/zoneminder.tmpfiles.in index f655a9c9f..f3acd0af7 100644 --- a/distros/redhat/systemd/zoneminder.tmpfiles.in +++ b/distros/redhat/systemd/zoneminder.tmpfiles.in @@ -1,3 +1,2 @@ -D @ZM_RUNDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_TMPDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@ From 8ea4bdca1d0d3435de37287129a136cf564879f4 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 4 Jan 2017 10:45:36 -0600 Subject: [PATCH 05/12] explicity set index.php as the only directoryindex --- distros/redhat/systemd/zoneminder.conf.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/distros/redhat/systemd/zoneminder.conf.in b/distros/redhat/systemd/zoneminder.conf.in index 564e4ccbd..005c959a6 100644 --- a/distros/redhat/systemd/zoneminder.conf.in +++ b/distros/redhat/systemd/zoneminder.conf.in @@ -11,6 +11,9 @@ RewriteRule ^/?(zm)(.*) https://%{SERVER_NAME}/$1$2 [R,L] Alias /zm "@ZM_WEBDIR@" + # explicitly set index.php as the only directoryindex + DirectoryIndex disabled + DirectoryIndex index.php SSLRequireSSL Options -Indexes +MultiViews +FollowSymLinks AllowOverride All From 0d7e1bcbc54203b19a0b29ef67a757102fff347e Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 4 Jan 2017 10:49:22 -0600 Subject: [PATCH 06/12] add php as a dependency only when we aren't using nginx --- distros/redhat/zoneminder.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index ad8615d06..0d7c5566c 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -64,7 +64,7 @@ BuildRequires: gcc gcc-c++ vlc-devel libcurl-devel libv4l-devel BuildRequires: ffmpeg-devel polkit-devel %{?with_nginx:Requires: nginx fcgiwrap php-fpm} -%{!?with_nginx:Requires: httpd} +%{!?with_nginx:Requires: httpd php} %{?with_php_mysqlnd:Requires: php-mysqlnd} %{?with_php_mysql:Requires: php-mysql} Requires: php-common php-gd cambozola polkit net-tools psmisc From 6b7e3a1b61d267f31b7223630b718266e289ceec Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 8 Jan 2017 17:37:03 -0600 Subject: [PATCH 07/12] rpm specfile changes --- distros/redhat/zoneminder.spec | 96 ++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 0d7c5566c..cb01847a4 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -1,8 +1,8 @@ %global zmuid_final apache %global zmgid_final apache -# In some cases older distros do not have this macro defined -%{!?make_build: %global make_build %{__make} %{?_smp_mflags} } +# Crud is configured as a git submodule +%global crud_version 3.0.10 %if "%{zmuid_final}" == "nginx" %global with_nginx 1 @@ -42,39 +42,78 @@ Group: System Environment/Daemons # jscalendar is LGPL (any version): http://www.dynarch.com/projects/calendar/ # Mootools is inder the MIT license: http://mootools.net/ # CakePHP is under the MIT license: https://github.com/cakephp/cakephp +# Crud is under the MIT license: https://github.com/FriendsOfCake/crud License: GPLv2+ and LGPLv2+ and MIT URL: http://www.zoneminder.com/ -Source: ZoneMinder-%{version}.tar.gz +Source0: https://github.com/ZoneMinder/ZoneMinder/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz +Source1: https://github.com/FriendsOfCake/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz -%{?with_init_systemd:BuildRequires: systemd-devel mariadb-devel perl-podlators} +%{?with_init_systemd:BuildRequires: systemd-devel} +%{?with_init_systemd:BuildRequires: mariadb-devel} +%{?with_init_systemd:BuildRequires: perl-podlators} %{?with_init_sysv:BuildRequires: mysql-devel} BuildRequires: cmake >= 2.8.7 +BuildRequires: gnutls-devel +BuildRequires: bzip2-devel +BuildRequires: pcre-devel +BuildRequires: libjpeg-turbo-devel +BuildRequires: findutils +BuildRequires: coreutils +BuildRequires: perl BuildRequires: perl-generators -BuildRequires: gnutls-devel bzip2-devel -BuildRequires: pcre-devel libjpeg-turbo-devel -BuildRequires: perl(Archive::Tar) perl(Archive::Zip) -BuildRequires: perl(Date::Manip) perl(DBD::mysql) -BuildRequires: perl(ExtUtils::MakeMaker) perl(LWP::UserAgent) -BuildRequires: perl(MIME::Entity) perl(MIME::Lite) -BuildRequires: perl(PHP::Serialization) perl(Sys::Mmap) -BuildRequires: perl(Time::HiRes) perl(Net::SFTP::Foreign) -BuildRequires: perl(Expect) perl(Sys::Syslog) -BuildRequires: gcc gcc-c++ vlc-devel libcurl-devel libv4l-devel -BuildRequires: ffmpeg-devel polkit-devel +BuildRequires: perl(Archive::Tar) +BuildRequires: perl(Archive::Zip) +BuildRequires: perl(Date::Manip) +BuildRequires: perl(DBD::mysql) +BuildRequires: perl(ExtUtils::MakeMaker) +BuildRequires: perl(LWP::UserAgent) +BuildRequires: perl(MIME::Entity) +BuildRequires: perl(MIME::Lite) +BuildRequires: perl(PHP::Serialization) +BuildRequires: perl(Sys::Mmap) +BuildRequires: perl(Time::HiRes) +BuildRequires: perl(Net::SFTP::Foreign) +BuildRequires: perl(Expect) +BuildRequires: perl(Sys::Syslog) +BuildRequires: gcc +BuildRequires: gcc-c++ +BuildRequires: vlc-devel +BuildRequires: libcurl-devel +BuildRequires: libv4l-devel +BuildRequires: ffmpeg-devel +BuildRequires: polkit-devel -%{?with_nginx:Requires: nginx fcgiwrap php-fpm} +%{?with_nginx:Requires: nginx} +%{?with_nginx:Requires: fcgiwrap} +%{?with_nginx:Requires: php-fpm} %{!?with_nginx:Requires: httpd php} +%{!?with_nginx:Requires: php} %{?with_php_mysqlnd:Requires: php-mysqlnd} %{?with_php_mysql:Requires: php-mysql} -Requires: php-common php-gd cambozola polkit net-tools psmisc -Requires: libjpeg-turbo vlc-core libcurl ffmpeg +Requires: php-common +Requires: php-gd +Requires: cambozola +Requires: net-tools +Requires: psmisc +Requires: polkit +Requires: libjpeg-turbo +Requires: vlc-core +Requires: libcurl +Requires: ffmpeg Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) -Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip) -Requires: perl(MIME::Entity) perl(MIME::Lite) perl(Net::SMTP) perl(Net::FTP) -Requires: perl(LWP::Protocol::https) perl(X10::ActiveHome) perl(Astro::SunTime) +Requires: perl(DBD::mysql) +Requires: perl(Archive::Tar) +Requires: perl(Archive::Zip) +Requires: perl(MIME::Entity) +Requires: perl(MIME::Lite) +Requires: perl(Net::SMTP) +Requires: perl(Net::FTP) +Requires: perl(LWP::Protocol::https) +Requires: perl(X10::ActiveHome) -%{?with_init_systemd:Requires(post): systemd systemd-sysv} +%{?with_init_systemd:Requires(post): systemd} +%{?with_init_systemd:Requires(post): systemd-sysv} %{?with_init_systemd:Requires(preun): systemd} %{?with_init_systemd:Requires(postun): systemd} @@ -100,7 +139,10 @@ designed to support as many cameras as you can attach to your computer without too much degradation of performance. %prep -%autosetup -n ZoneMinder-%{version} +%autosetup +%autosetup -a 1 +rmdir ./web/api/app/Plugin/Crud +mv -f crud-%{crud_version} ./web/api/app/Plugin/Crud # Change the following default values ./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin-zm/nph-zms @@ -285,11 +327,9 @@ rm -rf %{_docdir}/%{name}-%{version} %{perl_vendorlib}/WSSecurity* %{perl_vendorlib}/WSNotification* %{_mandir}/man*/* -%dir %{_libexecdir}/zoneminder -%{_libexecdir}/zoneminder/cgi-bin -%dir %{_datadir}/zoneminder -%{_datadir}/zoneminder/db -%{_datadir}/zoneminder/www + +%{_libexecdir}/zoneminder/ +%{_datadir}/zoneminder/ %{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules From dc6b2ed11439088ff62d85d2025e234321cf73cf Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 8 Jan 2017 18:17:28 -0600 Subject: [PATCH 08/12] clean up unnessary requires --- distros/redhat/zoneminder.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index cb01847a4..297fb0692 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -99,7 +99,6 @@ Requires: psmisc Requires: polkit Requires: libjpeg-turbo Requires: vlc-core -Requires: libcurl Requires: ffmpeg Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) Requires: perl(DBD::mysql) @@ -110,7 +109,6 @@ Requires: perl(MIME::Lite) Requires: perl(Net::SMTP) Requires: perl(Net::FTP) Requires: perl(LWP::Protocol::https) -Requires: perl(X10::ActiveHome) %{?with_init_systemd:Requires(post): systemd} %{?with_init_systemd:Requires(post): systemd-sysv} From 06fd760a2ac60f41a3dda874ba46337d22145fc6 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 9 Jan 2017 09:07:05 -0600 Subject: [PATCH 09/12] rpm specfile- use %{_localstatedir} macro --- distros/redhat/zoneminder.spec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 297fb0692..a3bb48865 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -146,7 +146,7 @@ mv -f crud-%{crud_version} ./web/api/app/Plugin/Crud ./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin-zm/nph-zms ./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes ./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm -./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload +./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR %{_localstatedir}/spool/zoneminder-upload ./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes ./utils/zmeditconfigdata.sh ZM_CHECK_FOR_UPDATES no ./utils/zmeditconfigdata.sh ZM_DYN_SHOW_DONATE_REMINDER no @@ -338,9 +338,9 @@ rm -rf %{_docdir}/%{name}-%{version} %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/sock %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/swap %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/temp -%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/log/zoneminder -%dir %attr(755,%{zmuid_final},%{zmgid_final}) /var/spool/zoneminder-upload -%dir %attr(755,%{zmuid_final},%{zmgid_final}) %ghost /var/run/zoneminder +%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/log/zoneminder +%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/spool/zoneminder-upload +%dir %attr(755,%{zmuid_final},%{zmgid_final}) %ghost %{_localstatedir}/run/zoneminder %changelog * Wed Dec 28 2016 Andrew Bauer - 1.30.1-2 From fa416ef8892d4c70926d65f603081fda28694818 Mon Sep 17 00:00:00 2001 From: Stefan Lindblom Date: Mon, 2 Jan 2017 09:09:53 +0100 Subject: [PATCH 10/12] Add MonitorPreset for Qihan IP cameras via RTSP --- db/zm_create.sql.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 24c73c8eb..50c4e9012 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -668,6 +668,8 @@ INSERT INTO MonitorPresets VALUES (NULL,'Foscam FI9821W FFMPEG H.264','Ffmpeg',N INSERT INTO MonitorPresets VALUES (NULL,'Loftek Sentinel PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,'','80','/videostream.cgi?user=&pwd=&resolution=32&rate=11',NULL,640,480,4,NULL,1,'13','',':@',100,100); INSERT INTO MonitorPresets VALUES (NULL,'Airlink 777W PTZ, 640x480, mjpeg','Remote','http',0,0,NULL,NULL,':@','80','/cgi/mjpg/mjpg.cgi',NULL,640,480,4,NULL,1,'7','',':@',100,100); INSERT INTO MonitorPresets VALUES (NULL,'SunEyes SP-P1802SWPTZ','Libvlc','/dev/video','0',255,'','rtpMulti','','80','rtsp://:554/11','',1920,1080,0,0.00,1,'16','-speed=64',':',100,33); +INSERT INTO MonitorPresets VALUES (NULL,'Qihan IP, 1280x720, RTP/RTSP','Ffmpeg','rtsp','rtpRtsp',255,'rtsp','rtpRtsp',NULL,554,'rtsp:///tcp_live/ch0_0',NULL,1280,720,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES (NULL,'Qihan IP, 1920x1080, RTP/RTSP','Ffmpeg','rtsp','rtpRtsp',255,'rtsp','rtpRtsp',NULL,554,'rtsp:///tcp_live/ch0_0',NULL,1920,1080,3,NULL,0,NULL,NULL,NULL,100,100); -- -- Add some zone preset values From fea5fa1b594efcd339f7f4488f5ec7150382a370 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Jan 2017 12:35:02 -0500 Subject: [PATCH 11/12] fix xtell should be -1 for move left --- web/skins/classic/includes/control_functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/includes/control_functions.php b/web/skins/classic/includes/control_functions.php index eb2a9cb15..0d92ab53c 100644 --- a/web/skins/classic/includes/control_functions.php +++ b/web/skins/classic/includes/control_functions.php @@ -253,7 +253,7 @@ function controlPanTilt( $monitor, $cmds )
-
+
From 55403219d899b96331548fdaea64b04cbecbbe42 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Jan 2017 12:35:38 -0500 Subject: [PATCH 12/12] fix regexp for direction in control command. Also log if the regexp doesn't match --- web/includes/control_functions.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/includes/control_functions.php b/web/includes/control_functions.php index dfbc8cb3e..d5fa06675 100644 --- a/web/includes/control_functions.php +++ b/web/includes/control_functions.php @@ -9,7 +9,7 @@ function buildControlCommand( $monitor ) $slow = 0.9; // Threshold for slow speed/timeouts $turbo = 0.9; // Threshold for turbo speed - if ( preg_match( '/^([a-z]+)([A-Z][a-z]+)([A-Z][a-z]+)+$/', $_REQUEST['control'], $matches ) ) + if ( preg_match( '/^([a-z]+)([A-Z][a-z]+)([A-Za-z]+)+$/', $_REQUEST['control'], $matches ) ) { $command = $matches[1]; $mode = $matches[2]; @@ -278,6 +278,8 @@ function buildControlCommand( $monitor ) } } } + } else { + Error("Invalid control parameter: " . $_REQUEST['control'] ); } } elseif ( isset($_REQUEST['x']) && isset($_REQUEST['y']) )