From 7fef8b87ad61e00b33a187b7a2314f2e266a852e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Jan 2017 12:17:23 -0500 Subject: [PATCH 01/52] Add Preset for IP Webcam --- db/zm_create.sql.in | 1 + 1 file changed, 1 insertion(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 0d6c853c9..91e401723 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -637,6 +637,7 @@ INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, jpeg','Remote','http','simp INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/GetData.cgi',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO `MonitorPresets` VALUES (NULL,'IP Webcam by Pavel Khlebovich 1920x1080','Remote','/dev/video','0',255,'http','simple','','8080','/video','',1920,1080,0,NULL,0,'0','','',100,100); INSERT INTO MonitorPresets VALUES (NULL,'VEO Observer, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); INSERT INTO MonitorPresets VALUES (NULL,'Blue Net Video Server, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/cgi-bin/image.cgi?control=0&id=admin&passwd=admin',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); INSERT into MonitorPresets VALUES (NULL,'ACTi IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',7070,'','/track',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); From 707444c39e87eb36f6ec3b67b03d5c3f2932125b Mon Sep 17 00:00:00 2001 From: Michael Barkdoll Date: Mon, 9 Oct 2017 09:44:45 -0500 Subject: [PATCH 02/52] Add files via upload --- .../lib/ZoneMinder/Control/TVIP672WI.pm | 590 ++++++++++++++++++ 1 file changed, 590 insertions(+) create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm new file mode 100644 index 000000000..4828b65b0 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm @@ -0,0 +1,590 @@ +# ========================================================================= +# +# ZoneMinder Trendnet TV-IP672WI IP Control Protocol Module, $Date: $, $Revision: $ +# Copyright (C) 2014 Vincent Giovannone +# Updated 2017 Michael Barkdoll +# +# +# ========================================================================== +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ========================================================================== +# +# This module contains the implementation of the Trendnet TV-IP672WI IP camera control +# protocol. +# +# Tested on Zoneminder 1.30.4 +# +# Under control capability: +# +# * Main: name it (suggest TVIP672WI), type is FFMPEG (or remote if you're using MJPEG), protocol is TVIP672WI +# * Main (more): Can wake, can sleep, can reset +# * Move: Can move, can move diagonally, can move mapped, can move relative +# * Pan: Can pan +# * Tilt: Can tilt +# +# * Presets: Has presets, num presets 20, has home preset (don't set presets via camera's web server, only set via ZM.) +# (I didn't test/use presets -MB) +# +# Under control tab in the monitor itself: +# +# * Controllable +# * Control type is the name you gave it in control capability above +# * Control device is the username and password you use to authenticate to the camera +# E.g., admin:password +# +# * Control address is the camera's ip address AND web port +# E.g., 192.168.1.100:80 +# Optionally, it can parse all username and password with the following format: +# http://admin:password@192.168.1.100:80 +# +# +# If using with anything but a TV-IP672WI (ex: TV-IP672PI), YOU MUST MATCH THE REALM TO MATCH YOUR CAMERA FURTHER DOWN! +# +# +# Due to how the TVIP672 represents presets internally, you MUST define the presets in order... i.e. 1,2,3,4... not 1,10,3,4. +# (see much further down for why, if you care...) +# +# Install this file with the following commands: +# +# sudo cp TVIP672WI.pm /usr/share/perl5/ZoneMinder/Control/ +# sudo chmod 755 /usr/share/perl5/ZoneMinder/Control/TVIP672WI.pm + + +package ZoneMinder::Control::TVIP672WI; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +# +# ******** YOU MUST CHANGE THE FOLLOWING LINES TO MATCH YOUR CAMERA! ********** +# +# I assume that "TV-IP672WI" would work for the TV-IP672PI, but can't test since I don't own one. +# +# TV-IP672WI works for the WI version, of course. +# +# Finally, the username is the username you'd like to authenticate as. +# +#our $REALM = 'TV-IP862IC'; +#our $REALM = 'TV-IP672PI'; + +our $REALM = 'TV-IP672WI'; +#our $REALM = 'TVIP672WI'; + +# $USERNAME and $PASSWORD are parsed from ControlDevice field in GUI +# E.g., username:password +# Note: values defined below are overriden by GUI values +our $USERNAME = ''; +our $PASSWORD = ''; + +# $ADDRESS is parsed from field, 'Control Address' +our $ADDRESS = ''; + +# ========================================================================== +# +# Trendnet TV-IP672PI Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +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(); + + my $controldevice = $self->{Monitor}->{ControlDevice}; + if ( $controldevice && $controldevice =~ m/\:/ ) { + my ( $adminname, $lastpass ) + = split(/\:/, $controldevice, 2); + if ( $adminname ) { + $USERNAME = $adminname; + #Error( "Username updated to: " . $USERNAME ); + } + if ( $lastpass ) { + $PASSWORD = $lastpass; + #Error( "Password updated to: " . $PASSWORD ); + } + } else { + if ( $controldevice ) { + $PASSWORD = $controldevice; + #Error( "Password updated to: " . $PASSWORD ); + } else { + Error ( "Unable to parse Control Device field: " . $controldevice ); + } + } + + my ( $protocol, $username, $password, $address ) + = $self->{Monitor}->{ControlAddress} =~ /^(http?:\/\/)?([^:]+):([^\/@]+)@(.*)$/; + if ( ( $username ) && ( $password ) && ( $address ) ) { + $USERNAME = $username; + $PASSWORD = $password; + $ADDRESS = $address; + #Error( "Set USERNAME: " . $USERNAME . "PASSWORD: " . $PASSWORD . "ADDRESS: " . $ADDRESS ); + } else { + if ( ! ( $controldevice ) ) { + Error( "Failed to parse auth from address"); + Error( "Unable to pull username and password for authentication from fields ControlAddress or ControlDevice" ); + Error( "Control script attempts to pull these values from field ControlDevice as username:password" ); + Error( "Optionally, these values can also be set at /usr/share/perl5/ZoneMinder/Control/TVIP672WI.pm" ); + } + $ADDRESS = $self->{Monitor}->{ControlAddress}; + } + if ( ! ( $ADDRESS =~ m/\:/ ) ) { + $ADDRESS .= ':80'; + Debug( "You generally need to also specify the port. I will append :80" ); + } + + Debug ( "Address is now: " . $ADDRESS ); + + use LWP::UserAgent; + use HTTP::Request::Common; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION ); + $self->{state} = 'open'; + # credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string) + $self->{ua}->credentials($ADDRESS,$REALM,$USERNAME,$PASSWORD); + +# Detect REALM + my $req = HTTP::Request->new( GET=>"http://".$ADDRESS."/cgi/ptdc.cgi" ); + my $res = $self->{ua}->request($req); + + if ( ! $res->is_success ) { + Debug("Need newer REALM"); + + if ( $res->status_line() eq '401 Unauthorized' ) { + my $headers = $res->headers(); + foreach my $k ( keys %$headers ) { + Error("Initial Header $k => $$headers{$k}"); + } # end foreach + if ( $$headers{'www-authenticate'} ) { + my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/; + if ( $tokens =~ /\w+="([^"]+)"/i ) { + $REALM = $1; + Debug( "Changing REALM to $REALM" ); + $self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD); + my $req = HTTP::Request->new( GET=>"http://".$ADDRESS."/cgi/ptdc.cgi" ); + my $res = $self->{ua}->request($req); + if ( ! $res->is_success ) { + Error ( "Unable to authenticate!!!" ); + } + } # end if + } else { + Error("No headers line"); + } # end if headers + } # end if $res->status_line() eq '401 Unauthorized' + } # end if ! $res->is_success +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + +# This routine is used for all moving, which are all GET commands... + + my $self = shift; + my $cmd = shift; + + my $result = undef; + + # Assuming you've placed your camera on a secure vlan network for ip cameras... + my $url = "http://".$USERNAME.":".$PASSWORD."@".$ADDRESS."/cgi/ptdc.cgi?command=".$cmd; + # The following didn't work with the TV-IP672WI; required authentication despite previous auth + #my $url = "http://".$ADDRESS."/cgi/ptdc.cgi?command=".$cmd; + my $req = HTTP::Request->new( GET=>$url ); + + Debug ("sendCmd command: " . $url ); + + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) { + $result = !undef; + } else { + if ( $res->status_line() eq '401 Unauthorized' ) { + Debug( "Error check failed, trying again: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); + Debug("Content was " . $res->content() ); + my $res = $self->{ua}->request($req); + if ( $res->is_success ) { + $result = !undef; + } else { + Debug("Content was " . $res->content() ); + } + } + if ( ! $result ) { + Debug( "Error check failed: '".$res->status_line()."' cmd:'".$cmd."'" ); + } + } + + return( $result ); +} + + + +sub sendCmdPost +{ + +# +# This routine is used for setting/clearing presets and IR commands, which are POST commands... +# + + my $self = shift; + my $url = shift; + my $cmd = shift; + + my $result = undef; + + if ($url eq undef) + { + Error ("url passed to sendCmdPost is undefined."); + return(-1); + } + + Debug ("sendCmdPost url: " . $url . " cmd: " . $cmd); + + my $req = HTTP::Request->new(POST => "http://".$ADDRESS.$url); + $req->content_type('application/x-www-form-urlencoded'); + $req->content($cmd); + + Debug ( "sendCmdPost credentials control address:'".$ADDRESS."' realm:'" . $REALM . "' username:'" . $USERNAME . "' password:'".$PASSWORD."'"); + + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "sendCmdPost Error check failed: '".$res->status_line()."' cmd:'".$cmd."'" ); + if ( $res->status_line() eq '401 Unauthorized' ) { + Error( "sendCmdPost Error check failed: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); + } else { + Error( "sendCmdPost Error check failed: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); + } # endif + } + + return( $result ); +} + + + +sub move +{ + my $self = shift; + my $panSteps = shift; + my $tiltSteps = shift; + + my $cmd = "set_relative_pos&posX=$panSteps&posY=$tiltSteps"; + $self->sendCmd( $cmd ); +} + +sub moveRelUpLeft +{ + my $self = shift; + Debug( "Move Up Left" ); + $self->move(-3, 3); +} + +sub moveRelUp +{ + my $self = shift; + Debug( "Move Up" ); + $self->move(0, 3); +} + +sub moveRelUpRight +{ + my $self = shift; + Debug( "Move Up Right" ); + $self->move(3, 3); +} + +sub moveRelLeft +{ + my $self = shift; + Debug( "Move Left" ); + $self->move(-3, 0); +} + +sub moveRelRight +{ + my $self = shift; + Debug( "Move Right" ); + $self->move(3, 0); +} + +sub moveRelDownLeft +{ + my $self = shift; + Debug( "Move Down Left" ); + $self->move(-3, -3); +} + +sub moveRelDown +{ + my $self = shift; + Debug( "Move Down" ); + $self->move(0, -3); +} + +sub moveRelDownRight +{ + my $self = shift; + Debug( "Move Down Right" ); + $self->move(3, -3); +} + + +# moves the camera to center on the point that the user clicked on in the video image. +# This isn't mega accurate but good enough for most purposes + +sub moveMap +{ + + # If the camera moves too much, increase hscale and vscale. (...if it doesn't move enough, try decreasing!) + # They scale the movement and are here to compensate for manufacturing variation. + # It's never going to be perfect, so just get somewhere in the ballpark and call it a day. + # (Don't forget to kill the zmcontrol process while tweaking!) + + # 1280x800 + my $hscale = 31; + my $vscale = 25; + + # 1280x800 with fisheye + #my $hscale = 15; + #my $vscale = 15; + + # 640x400 + #my $hscale = 14; + #my $vscale = 12; + + + my $self = shift; + my $params = shift; + my $xcoord = $self->getParam( $params, 'xcoord' ); + my $ycoord = $self->getParam( $params, 'ycoord' ); + + my $hor = ($xcoord - ($self->{Monitor}->{Width} / 2))/$hscale; + my $ver = ($ycoord - ($self->{Monitor}->{Height} / 2))/$vscale; + + $hor = int($hor); + $ver = -1 * int($ver); + + Debug( "Move Map to $xcoord,$ycoord, hor=$hor, ver=$ver" ); + $self->move( $hor, $ver ); +} + + +# **** PRESETS **** +# +# OK, presets work a little funky but they DO work, provided you define them in order and don't skip any. +# +# The problem is that when you load the web page for this camera, it gives a list of preset names tied to index numbers. +# So let's say you have four presets... A, B, C, and D, and defined them in that order. +# So A is index 0, B is index 1, C is index 2, D is index 3. When you tell the camera to go to a preset, you actually tell it by number, not by name. +# (So "Go to D" is really "go to index 3".) +# +# Now let's say somebody deletes C via the camera's web GUI. The camera re-numbers the existing presets A=0, B=1, D=2. +# There's really no easy way for ZM to discover this re-numbering, so zoneminder would still send "go to preset 3" thinking +# it's telling the camera to go to point D. In actuality it's telling the camera to go to a preset that no longer exists. +# +# As long as you define your presets in order (i.e. define preset 1, then preset 2, then preset 3, etc.) everything will work just +# fine in ZoneMinder. +# +# (Home preset needs to be set via the camera's web gui, and is unaffected by any of this.) +# +# So that's the limitation: DEFINE YOUR PRESETS IN ORDER THROUGH (and only through!) ZM AND DON'T SKIP ANY. +# + + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + my $cmd = "presetName=$preset&command=del"; + my $url = "/eng/admin/cam_control.cgi"; + Debug ("presetClear: " . $preset . " cmd: " . $cmd); + $self->sendCmdPost($url,$cmd); +} + + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + my $cmd = "presetName=$preset&command=add"; + my $url = "/eng/admin/cam_control.cgi"; + Debug ("presetSet " . $preset . " cmd: " . $cmd); + $self->sendCmdPost ($url,$cmd); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + $preset = $preset - 1; + Debug( "Goto Preset $preset" ); + my $cmd = "goto_preset_position&index=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "go_home"; + $self->sendCmd( $cmd ); +} + + +# +# **** IR CONTROLS **** +# +# +# Wake: Force IR on, always. (always night mode) +# +# Sleep: Force IR off, always. (always day mode) +# +# Reset: Automatic IR mode. (day/night mode determined by camera) +# + + +sub wake +{ + # force IR on ("always night mode") + + my $self = shift; + my $url = "/eng/admin/adv_audiovideo.cgi"; + my $cmd = "irMode=3"; + + Debug("Wake -- IR on"); + + $self->sendCmdPost ($url,$cmd); +} + +sub sleep +{ + # force IR off ("always day mode") + + my $self=shift; + my $url = "/eng/admin/adv_audiovideo.cgi"; + my $cmd = "irMode=2"; + + Debug("Sleep -- IR off"); + + $self->sendCmdPost ($url,$cmd); +} + +sub reset +{ + # IR auto + + my $self=shift; + my $url = "/eng/admin/adv_audiovideo.cgi"; + my $cmd = "irMode=0"; + + Debug("Reset -- IR auto"); + + $self->sendCmdPost ($url,$cmd); +} + + +1; +__END__ +# Below is stub documentation for your module. You'd better edit it! + +=head1 NAME + +ZoneMinder::Database - Perl extension for Trendnet TVIP672 + +=head1 SYNOPSIS + + use ZoneMinder::Database; + stuff this in /usr/share/perl5/ZoneMinder/Control , then eat a sandwich + +=head1 DESCRIPTION + +Stub documentation for Trendnet TVIP672, created by Vince, updated by Michael. + +=head2 EXPORT + +None by default. + + + +=head1 SEE ALSO + +Read the comments at the beginning of this file to see the usage for zoneminder 1.25.0 + + +=head1 AUTHOR + +Vincent Giovannone, I'd rather you not email me; sure no problem... + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2014 by Vincent Giovannone + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.8.3 or, +at your option, any later version of Perl 5 you may have available. + + +=cut \ No newline at end of file From fa7f6088c886d91dbfd7865c28ac6acd5d5680e0 Mon Sep 17 00:00:00 2001 From: Michael Barkdoll Date: Mon, 9 Oct 2017 11:14:13 -0500 Subject: [PATCH 03/52] Update zm_create.sql.in Add support for TVIP672WI --- db/zm_create.sql.in | 1 + 1 file changed, 1 insertion(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 62424c286..fab696ac7 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -603,6 +603,7 @@ INSERT INTO `Controls` VALUES (NULL,'Netcat ONVIF','Ffmpeg','Netcat',0,0,1,1,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); INSERT INTO `Controls` VALUES (NULL,'Maginon Supra IPC','cURL','MaginonIPC',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,4,0,1,1,1,0,0,1,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,'TVIP672WI','Remote','TVIP672WI',1,1,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,0,0,0,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); -- -- Add some monitor preset values From 48b91c5544fdbdc6adc61691a023a3e145613efb Mon Sep 17 00:00:00 2001 From: Roman Dissertori Date: Sat, 28 Jul 2018 15:26:02 +0200 Subject: [PATCH 04/52] Bugfix in Control and added new Camera (#2171) * fixed control typos missing word "s" for "Controls" Table for database queries * added Dericam P2 camera Control * fixed missing CanReset column * Update DericamP2.pm * added some more missing controls CanSleep, CanWake * Update DericamP2.pm * Update DericamP2.pm * Update DericamP2.pm * Update DericamP2.pm * Update DericamP2.pm * Update DericamP2.pm * Update DericamP2.pm * Update zm_create.sql.in --- db/zm_create.sql.in | 1 + .../lib/ZoneMinder/Control/DericamP2.pm | 475 ++++++++++++++++++ web/includes/Control.php | 5 +- 3 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/DericamP2.pm diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index cf7c1150d..a6284bc79 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -778,6 +778,7 @@ INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-411','Ffmpeg','Reolink',0,0,1,1 INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-420','Ffmpeg','Reolink',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,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); INSERT INTO `Controls` VALUES (NULL,'D-LINK DCS-3415','Remote','DCS3415',0,0,0,1,0,0,0,0,0,0,0,0,0,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,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,'IOS Camera','Ffmpeg','IPCAMIOS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,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,'Dericam P2','Ffmpeg','DericamP2',0,1,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,10,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,45,0,0,1,0,0,0,0,1,1,45,0,0,0,0); -- -- Add some monitor preset values -- diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/DericamP2.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/DericamP2.pm new file mode 100644 index 000000000..90221c770 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/DericamP2.pm @@ -0,0 +1,475 @@ +# ========================================================================== +# +# ZoneMinder Dericam P2 Control Protocol Module +# Copyright (C) Roman Dissertori +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ========================================================================== +# +# This module contains the implementation of the Dericam P2 device control protocol +# +package ZoneMinder::Control::DericamP2; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our %CamParams = (); + +# ========================================================================== +# +# Dericam P2 Control Protocol +# +# On ControlAddress use the format : +# USERNAME:PASSWORD@ADDRESS:PORT +# eg : admin:@10.1.2.1:80 +# zoneminder:zonepass@10.0.100.1:40000 +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + my $result = undef; + printMsg( $cmd, "Tx" ); + + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + Info( "http://".$self->{Monitor}->{ControlAddress}."/$cmd".$self->{Monitor}->{ControlDevice} ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed:'".$res->status_line()."'" ); + } + + return( $result ); +} + +sub getCamParams +{ + my $self = shift; + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=getimageattr"; + + my $req = $self->sendCmd( $cmd ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + # Parse results setting values in %FCParams + my $content = $res->decoded_content; + + while ($content =~ s/var\s+([^=]+)=([^;]+);//ms) { + $CamParams{$1} = $2; + } + } + else + { + Error( "Error check failed:'".$res->status_line()."'" ); + } +} + +#autoStop +#This makes use of the ZoneMinder Auto Stop Timeout on the Control Tab +sub autoStop +{ + my $self = shift; + my $stop_command = shift; + my $autostop = shift; + if( $stop_command && $autostop) + { + Debug( "Auto Stop" ); + usleep( $autostop ); + my $cmd = "decoder_control.cgi?command=".$stop_command; + $self->sendCmd( $cmd ); + } + +} + +# Reset the Camera +sub reset +{ + my $self = shift; + Debug( "Camera Reset" ); + # Move to default position + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-act=home"; + $self->sendCmd( $cmd ); + + # Reset all other values to default + $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-image_type=1&-default=on"; + $self->sendCmd( $cmd ); +} + +# Reboot Camera (on Sleep button) +sub sleep +{ + my $self = shift; + Debug( "Camera Reboot" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-act=sysreboot"; + $self->sendCmd( $cmd ); +} + +# Stop the Camera +sub moveStop +{ + my $self = shift; + Debug( "Camera Stop" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-act=stop"; + $self->sendCmd( $cmd ); +} + +#Up Arrow +sub moveConUp +{ + my $self = shift; + my $stop_command = "1"; + Debug( "Move Up" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=up&-speed=45"; + $self->sendCmd( $cmd ); + #$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} ); +} + +#Down Arrow +sub moveConDown +{ + my $self = shift; + my $stop_command = "3"; + Debug( "Move Down" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=down&-speed=45"; + $self->sendCmd( $cmd ); + #$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} ); +} + +#Left Arrow +sub moveConLeft +{ + my $self = shift; + my $stop_command = "5"; + Debug( "Move Left" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=left&-speed=45"; + $self->sendCmd( $cmd ); + #$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} ); +} + +#Right Arrow +sub moveConRight +{ + my $self = shift; + my $stop_command = "7"; + Debug( "Move Right" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=right&-speed=45"; + $self->sendCmd( $cmd ); + #$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} ); +} + +#Zoom In +sub zoomConTele +{ + my $self = shift; + Debug( "Zoom Tele" ); + my $cmd = "decoder_control.cgi?command=18"; + $self->sendCmd( $cmd ); +} + +#Zoom Out +sub zoomConWide +{ + my $self = shift; + Debug( "Zoom Wide" ); + my $cmd = "decoder_control.cgi?command=16"; + $self->sendCmd( $cmd ); +} + +#Diagonally Up Right Arrow +#This camera does not have builtin diagonal commands so we emulate them +sub moveConUpRight +{ + my $self = shift; + Debug( "Move Diagonally Up Right" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=upright&-speed=45"; + $self->sendCmd( $cmd ); +} + +#Diagonally Down Right Arrow +#This camera does not have builtin diagonal commands so we emulate them +sub moveConDownRight +{ + my $self = shift; + Debug( "Move Diagonally Down Right" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=downright&-speed=45"; + $self->sendCmd( $cmd ); +} + +#Diagonally Up Left Arrow +#This camera does not have builtin diagonal commands so we emulate them +sub moveConUpLeft +{ + my $self = shift; + Debug( "Move Diagonally Up Left" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=upleft&-speed=45"; + $self->sendCmd( $cmd ); +} + +#Diagonally Down Left Arrow +#This camera does not have builtin diagonal commands so we emulate them +sub moveConDownLeft +{ + my $self = shift; + Debug( "Move Diagonally Down Left" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=downnleft&-speed=45"; + $self->sendCmd( $cmd ); +} + +#Set Camera Preset +#Presets must be translated into values internal to the camera +#Those values are: 30,32,34,36,38,40,42,44 for presets 1-8 respectively +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Set Preset $preset" ); + + if (( $preset >= 1 ) && ( $preset <= 8 )) { + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=preset&-act=set&-number=".(($preset*2) + 28); + $self->sendCmd( $cmd ); + } +} + +#Recall Camera Preset +#Presets must be translated into values internal to the camera +#Those values are: 31,33,35,37,39,41,43,45 for presets 1-8 respectively +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Goto Preset $preset" ); + + if (( $preset >= 1 ) && ( $preset <= 8 )) { + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=preset&-act=goto&-number=".(($preset*2) + 29); + $self->sendCmd( $cmd ); + } + + if ( $preset == 9 ) { + $self->horizontalPatrol(); + } + + if ( $preset == 10 ) { + $self->verticalPatrol(); + } +} + +#Horizontal Patrol +sub horizontalPatrol +{ + my $self = shift; + Debug( "Horizontal Patrol" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=hscan"; + $self->sendCmd( $cmd ); +} + +#Vertical Patrol +sub verticalPatrol +{ + my $self = shift; + Debug( "Vertical Patrol" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=ptzctrl&-step=0&-act=vscan"; + $self->sendCmd( $cmd ); +} + +# Increase Brightness +sub irisAbsOpen +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'brightness'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'brightness'} += $step; + $CamParams{'brightness'} = 100 if ($CamParams{'brightness'} > 100); + Debug( "Increase Brightness" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-brightness=".$CamParams{'brightness'}; + $self->sendCmd( $cmd ); +} + +# Decrease Brightness +sub irisAbsClose +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'brightness'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'brightness'} -= $step; + $CamParams{'brightness'} = 0 if ($CamParams{'brightness'} < 0); + Debug( "Decrease Brightness" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-brightness=".$CamParams{'brightness'}; + $self->sendCmd( $cmd ); +} + +# Increase Contrast +sub whiteAbsIn +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'contrast'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'contrast'} += $step; + $CamParams{'contrast'} = 100 if ($CamParams{'contrast'} > 100); + Debug( "Increase Contrast" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-contrast=".$CamParams{'contrast'}; + $self->sendCmd( $cmd ); +} + +# Decrease Contrast +sub whiteAbsOut +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'contrast'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'contrast'} -= $step; + $CamParams{'contrast'} = 0 if ($CamParams{'contrast'} < 0); + Debug( "Decrease Contrast" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-contrast=".$CamParams{'contrast'}; + $self->sendCmd( $cmd ); +} + +#TODO Saturation cgi-bin/hi3510/param.cgi?cmd=setimageattr&-saturation=44 [0-255] +sub satIncrease +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'saturation'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'saturation'} += $step; + $CamParams{'saturation'} = 255 if ($CamParams{'saturation'} > 255); + Debug( "Increase Saturation" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-saturation=".$CamParams{'saturation'}; + $self->sendCmd( $cmd ); +} + +sub satDecrease +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'saturation'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'saturation'} -= $step; + $CamParams{'saturation'} = 0 if ($CamParams{'saturation'} < 0); + Debug( "Decrease Saturation" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-saturation=".$CamParams{'saturation'}; + $self->sendCmd( $cmd ); +} +#TODO Sharpness cgi-bin/hi3510/param.cgi?cmd=setimageattr&-sharpness=37 [0-100] +sub sharpIncrease +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'sharpness'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'sharpness'} += $step; + $CamParams{'sharpness'} = 100 if ($CamParams{'sharpness'} > 100); + Debug( "Increase Sharpness" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-sharpness=".$CamParams{'sharpness'}; + $self->sendCmd( $cmd ); +} + +sub sharpDecrease +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'sharpness'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'sharpness'} -= $step; + $CamParams{'sharpness'} = 0 if ($CamParams{'sharpness'} < 0); + Debug( "Decrease Sharpness" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-sharpness=".$CamParams{'sharpness'}; + $self->sendCmd( $cmd ); +} + +#TODO Hue cgi-bin/hi3510/param.cgi?cmd=setimageattr&-hue=37 [0-100] +sub hueIncrease +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'hue'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'hue'} += $step; + $CamParams{'hue'} = 100 if ($CamParams{'hue'} > 100); + Debug( "Increase Hue" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-hue=".$CamParams{'hue'}; + $self->sendCmd( $cmd ); +} + +sub hueDecrease +{ + my $self = shift; + my $params = shift; + $self->getCamParams() unless($CamParams{'hue'}); + my $step = $self->getParam( $params, 'step' ); + + $CamParams{'hue'} -= $step; + $CamParams{'hue'} = 0 if ($CamParams{'hue'} < 0); + Debug( "Decrease Hue" ); + my $cmd = "cgi-bin/hi3510/param.cgi?cmd=setimageattr&-hue=".$CamParams{'hue'}; + $self->sendCmd( $cmd ); +} + +1; diff --git a/web/includes/Control.php b/web/includes/Control.php index de5f221ff..74beeca05 100644 --- a/web/includes/Control.php +++ b/web/includes/Control.php @@ -12,6 +12,9 @@ private $defaults = array( 'CanMoveRel' => 0, 'CanMoveCon' => 0, 'CanPan' => 0, + 'CanReset' => 0, + 'CanSleep' => 0, + 'CanWake' => 0, 'MinPanRange' => NULL, 'MaxPanRange' => NULL, 'MinPanStep' => NULL, @@ -103,7 +106,7 @@ private $defaults = array( if ( $IdOrRow ) { $row = NULL; if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { - $row = dbFetchOne( 'SELECT * FROM Control WHERE Id=?', NULL, array( $IdOrRow ) ); + $row = dbFetchOne( 'SELECT * FROM Controls WHERE Id=?', NULL, array( $IdOrRow ) ); if ( ! $row ) { Error("Unable to load Control record for Id=" . $IdOrRow ); } From 363e1dda973cc8515d9a6e918e378d4ba58e62f2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 31 Jul 2018 10:15:26 -0400 Subject: [PATCH 05/52] Add some more Monitor defaults, mainly Refresh which gets called in watch.js.php --- web/includes/Monitor.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 8fc69a9cd..efa530c0a 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -9,17 +9,19 @@ private $defaults = array( 'Name' => '', 'StorageId' => 0, 'ServerId' => 0, + 'Type' => 'Ffmpeg', 'Function' => 'None', 'Enabled' => 1, + 'LinkedMonitors' => null, 'Width' => null, 'Height' => null, 'Orientation' => null, 'AnalysisFPSLimit' => null, 'ZoneCount' => 0, 'Triggers' => null, - 'Type' => 'Ffmpeg', 'MaxFPS' => null, 'AlarmMaxFPS' => null, + 'Refresh' => null, ); private $status_fields = array( 'AnalysisFPS' => null, From ee97dc39dc37b6c996d63a8e4a05e561d1af034a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 31 Jul 2018 10:22:13 -0400 Subject: [PATCH 06/52] Add Refresh column to Monitors table. Explicitly put it after ZoneCount in the update.sql --- db/zm_create.sql.in | 1 + db/zm_update-1.31.43.sql | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index a6284bc79..966fa9023 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -517,6 +517,7 @@ CREATE TABLE `Monitors` ( `ArchivedEvents` int(10) default NULL, `ArchivedEventDiskSpace` bigint default NULL, `ZoneCount` TINYINT NOT NULL DEFAULT 0, + `Refresh` int(10) unsigned default NULL, PRIMARY KEY (`Id`) ) ENGINE=@ZM_MYSQL_ENGINE@; diff --git a/db/zm_update-1.31.43.sql b/db/zm_update-1.31.43.sql index d8d6eaefd..05a92288e 100644 --- a/db/zm_update-1.31.43.sql +++ b/db/zm_update-1.31.43.sql @@ -16,7 +16,7 @@ SET @s = (SELECT IF( AND column_name = 'Refresh' ) > 0, "SELECT 'Column Refresh exists in Monitors'", -"ALTER TABLE Monitors ADD `Refresh` int(10) unsigned default NULL" +"ALTER TABLE Monitors ADD `Refresh` int(10) unsigned default NULL AFTER `ZoneCount`" )); PREPARE stmt FROM @s; From 11cedb43351776ed17434ad808d23e6145f7030c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 31 Jul 2018 10:27:34 -0400 Subject: [PATCH 07/52] repeat the update that adds Refresh to Monitors. Bump version. --- db/zm_update-1.31.45.sql | 23 +++++++++++++++++++++++ version | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 db/zm_update-1.31.45.sql diff --git a/db/zm_update-1.31.45.sql b/db/zm_update-1.31.45.sql new file mode 100644 index 000000000..c3be6c4cd --- /dev/null +++ b/db/zm_update-1.31.45.sql @@ -0,0 +1,23 @@ +-- +-- This updates a 1.31.44 database to 1.31.45 +-- +-- Add WebSite enum to Monitor.Type +-- Add Refresh column to Monitors table + +-- This is the same as the update to 1.31.43, but due to Refresh not being added to zm_create.sql.in we need to have it +-- again in order to fix people who did a fresh install from 1.31.43 or 1.31.44. +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Monitors' + AND table_schema = DATABASE() + AND column_name = 'Refresh' + ) > 0, +"SELECT 'Column Refresh exists in Monitors'", +"ALTER TABLE Monitors ADD `Refresh` int(10) unsigned default NULL AFTER `ZoneCount`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/version b/version index 856307b22..6701dcb1c 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.44 +1.31.45 From 63153f05be25dbdeb37ffbb941fbb8696d962e23 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 31 Jul 2018 12:25:00 -0500 Subject: [PATCH 08/52] bump version in rpm specfile --- 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 a9278891e..042abb40e 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -26,7 +26,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.31.44 +Version: 1.31.45 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons From 6ad732e419d7086954ce2c722097ab09a7aee0b5 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 31 Jul 2018 13:01:01 -0500 Subject: [PATCH 09/52] retrieve greip data rather than the ip (#2173) --- scripts/zmtelemetry.pl.in | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/zmtelemetry.pl.in b/scripts/zmtelemetry.pl.in index c23240891..592ccc295 100644 --- a/scripts/zmtelemetry.pl.in +++ b/scripts/zmtelemetry.pl.in @@ -33,6 +33,7 @@ use LWP::UserAgent; use Sys::MemInfo qw(totalmem); use Sys::CPU qw(cpu_count); use POSIX qw(strftime uname); +use JSON::MaybeXS; $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; @@ -87,7 +88,7 @@ while( 1 ) { # We should keep *BSD systems in mind when calling system commands my %telemetry; $telemetry{uuid} = getUUID($dbh); - $telemetry{ip} = getIP(); + ($telemetry{city}, $telemetry{region}, $telemetry{country}, $telemetry{latitude}, $telemetry{longitude}) = getGeo(); $telemetry{timestamp} = strftime( '%Y-%m-%dT%H:%M:%S%z', localtime() ); $telemetry{monitor_count} = countQuery($dbh,'Monitors'); $telemetry{event_count} = countQuery($dbh,'Events'); @@ -203,22 +204,25 @@ sub getUUID { return $uuid; } -# Retrieves the local server's external IP address -sub getIP { - my $ipaddr = '0.0.0.0'; +# Retrieve this server's general location information from a GeoIP database +sub getGeo { + my $unknown = 'Unknown'; + my $endpoint = 'https://ipinfo.io/geo'; my $ua = LWP::UserAgent->new; - my $server_endpoint = 'https://wiki.zoneminder.com/ip.php'; - - my $req = HTTP::Request->new(GET => $server_endpoint); + my $req = HTTP::Request->new(GET => $endpoint); my $resp = $ua->request($req); + my $resp_msg = $resp->decoded_content; + my $resp_code = $resp->code; if ($resp->is_success) { - $ipaddr = $resp->decoded_content; + my $content = decode_json( $resp_msg ); + (my $latitude, my $longitude) = split /,/, $content->{loc}; + return ($content->{city}, $content->{region}, $content->{country}, $latitude, $longitude); + } else { + Warning("Geoip data retrieval returned HTTP POST error code: $resp_code"); + Debug("Geoip data retrieval failure response message: $resp_msg"); + return ($unknown, $unknown, $unknown, $unknown); } - - Debug("Found external ip address of: $ipaddr"); - - return $ipaddr; } # As the name implies, just your average mysql count query From c8ed12f573546da6268aed85ca6cde8244262c9a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 2 Aug 2018 09:49:40 -0500 Subject: [PATCH 10/52] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 5f80fe591..4e33ce4e0 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,6 @@ You should only file an issue if you found a bug. Feature and enhancement requests, general discussions and support questions should occur in one of the following areas: -- The ZoneMinder IRC channel - irc.freenode.net #zoneminder +- The [ZoneMinder-Chat Slack channel](https://zoneminder-chat.herokuapp.com/) - The [ZoneMinder Forum](https://forums.zoneminder.com/) **Do not post feature or enhancement requests, general discussions or support questions here.** From a0e67da51d3a665c74f27b0032782400f04e8217 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 2 Aug 2018 15:40:33 -0400 Subject: [PATCH 11/52] Improve loging around writing out analysis frames --- src/zm_event.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index bc039a2f5..713b9728d 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -289,7 +289,7 @@ bool Event::WriteFrameImage(Image *image, struct timeval timestamp, const char * int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default bool rc; -Debug(3, "Writing image to %s", event_file ); +Debug(3, "Writing image to %s", event_file); if ( !config.timestamp_on_capture ) { // stash the image we plan to use in another pointer regardless if timestamped. @@ -594,11 +594,12 @@ Debug(3, "Writing video"); max_score = score; if ( alarm_image ) { - snprintf(event_file, sizeof(event_file), staticConfig.analyse_file_format, path, frames); - - Debug(1, "Writing analysis frame %d", frames); if ( monitor->GetOptSaveJPEGs() & 2 ) { - WriteFrameImage(alarm_image, timestamp, event_file, true); + snprintf(event_file, sizeof(event_file), staticConfig.analyse_file_format, path, frames); + Debug(1, "Writing analysis frame %d", frames); + if ( ! WriteFrameImage(alarm_image, timestamp, event_file, true) ) { + Error("Failed to write analysis frame image"); + } } } } From b72d520e02a859fbe29a4395341e04ace39030d2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Aug 2018 10:02:42 -0400 Subject: [PATCH 12/52] implement the ability to pass a disabled option to htmlSelect. Use it to disable the h264 passthrough option for non-ffmpeg monitors. Instead of disappearing it. --- web/includes/functions.php | 40 +++++++++++++++++++++-------- web/skins/classic/views/monitor.php | 4 ++- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 319ff1774..09a86c03c 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -432,20 +432,38 @@ function htmlSelect( $name, $contents, $values, $behaviours=false ) { } } - return "'; + return "'; } -function htmlOptions( $contents, $values ) { - $html = ''; - foreach ( $contents as $value=>$text ) { - if ( is_array( $text ) ) - $text = $text['Name']; - else if ( is_object( $text ) ) - $text = $text->Name(); - $selected = is_array( $values ) ? in_array( $value, $values ) : !strcmp($value, $values); - $html .= ""; +function htmlOptions($contents, $values) { + $options_html = ''; + + foreach ( $contents as $value=>$option ) { + $disabled = 0; + $text = ''; + if ( is_array($option) ) { + + if ( isset($option['Name']) ) + $text = $option['Name']; + else if ( isset($option['text']) ) + $text = $option['text']; + + if ( isset($option['disabled']) ) { + $disabled = $option['disabled']; + Error("Setting to disabled"); + } + } else if ( is_object($option) ) { + $text = $option->Name(); + } else { + $text = $option; + } + $selected = is_array($values) ? in_array($value, $values) : !strcmp($value, $values); + $options_html .= ""; } - return $html; + return $options_html; } function truncText( $text, $length, $deslash=1 ) { diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 9867298d5..92d6325bd 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -924,7 +924,9 @@ if ( $monitor->Type() == 'Local' ) { 1 => 'X264 Encode', ); if ($monitor->Type() == 'Ffmpeg' ) - $videowriteropts[2]='H264 Camera Passthrough'; + $videowriteropts[2] = 'H264 Camera Passthrough'; + else + $videowriteropts[2] = array('text'=>'H264 Camera Passthrough - only for FFMPEG','disabled'=>1); echo htmlselect( 'newMonitor[VideoWriter]', $videowriteropts, $monitor->VideoWriter() ); ?> From 328277536e7a1e6a8c8b7cdc23f46b4d32f1b89b Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 3 Aug 2018 10:18:11 -0500 Subject: [PATCH 13/52] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3bdf1ffd1..8f607c0c0 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ ZoneMinder [![Build Status](https://travis-ci.org/ZoneMinder/zoneminder.png)](https://travis-ci.org/ZoneMinder/zoneminder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received) +[![Join Slack](https://github.com/ozonesecurity/ozonebase/blob/master/img/slacksm.png?raw=true)](https://zoneminder-chat.herokuapp.com) + All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org ## Overview From dbdb9680c04bdbe284b75e69d12f2708f6d244b9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 2 Aug 2018 06:52:36 -0400 Subject: [PATCH 14/52] exit on HUP to free up memory. --- scripts/zmfilter.pl.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 1504c0aa3..cfea3bfe4 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -98,6 +98,11 @@ use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|) logInit($filter_id?(id=>'zmfilter_'.$filter_id):()); sub HupHandler { + # This idea at this time is to just exit, freeing up the memory. + # zmfilter.pl will be respawned by zmdc. + TermHandler(); + return; + Info('Received HUP, reloading'); ZoneMinder::Object::init_cache(); &ZoneMinder::Logger::logHupHandler(); From 23ddc83ad42dec1adba2d2479172687437454da2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 8 Aug 2018 09:59:46 -0400 Subject: [PATCH 15/52] fix_2167 (#2168) * Populate a global from the session on every request. Use the object instead of using allowedMonitors in session. * fix when gets loaded. * use for auth, and add Monitor Edit checks to Zone add/delete/edit * add back the ZM_OPT_USE_AUTH test for being logged in in AppController * Update permissions code to use * change quotes * Update permission code to use * Use instal of session for systemPermission * deprecate montiorPermision in session * use instead of session streamPermission * move login code back into AppController. Has to be done for every request * deprecate eventPermission, controlPermission and systemPermission in session. * handle auth params in query string as well as post * exit on HUP to free up memory. * add missing global user * system should be System --- web/api/app/Controller/AppController.php | 63 +++--- web/api/app/Controller/EventsController.php | 40 ++-- web/api/app/Controller/HostController.php | 102 +--------- web/api/app/Controller/MonitorsController.php | 36 ++-- web/api/app/Controller/ServersController.php | 66 ++++--- web/api/app/Controller/StatesController.php | 185 +++++++++--------- web/api/app/Controller/ZonesController.php | 34 +++- 7 files changed, 247 insertions(+), 279 deletions(-) diff --git a/web/api/app/Controller/AppController.php b/web/api/app/Controller/AppController.php index d48f853e3..692769ef0 100644 --- a/web/api/app/Controller/AppController.php +++ b/web/api/app/Controller/AppController.php @@ -60,30 +60,47 @@ class AppController extends Controller { // for role and deny API access in future // Also checking to do this only if ZM_OPT_USE_AUTH is on public function beforeFilter() { - $this->loadModel('Config'); - - $options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_API')); - $config = $this->Config->find('first', $options); - $zmOptApi = $config['Config']['Value']; - - if ( $zmOptApi != '1' ) { + if ( ! ZM_OPT_USE_API ) { throw new UnauthorizedException(__('API Disabled')); return; - } - // We need to reject methods that are not authenticated - // besides login and logout - if ( - strcasecmp($this->params->action, 'login') - && - strcasecmp($this->params->action,"logout") - ) { - if ( !$this->Session->read('user.Username') ) { - throw new UnauthorizedException(__('Not Authenticated')); - return; - } else if ( !$this->Session->read('user.Enabled') ) { - throw new UnauthorizedException(__('User is not enabled')); - return; - } - } + } + + # For use throughout the app. If not logged in, this will be null. + global $user; + $user = $this->Session->read('user'); + + if ( ZM_OPT_USE_AUTH ) { + require_once '../../../includes/auth.php'; + + $mUser = $this->request->query('user') ? $this->request->query('user') : $this->request->data('user'); + $mPassword = $this->request->query('pass') ? $this->request->query('pass') : $this->request->data('pass'); + $mAuth = $this->request->query('auth') ? $this->request->query('auth') : $this->request->data('auth'); + + if ( $mUser and $mPassword ) { + $user = userLogin($mUser, $mPassword); + if ( !$user ) { + throw new UnauthorizedException(__('User not found or incorrect password')); + return; + } + } else if ( $mAuth ) { + $user = getAuthUser($mAuth); + if ( !$user ) { + throw new UnauthorizedException(__('Invalid Auth Key')); + return; + } + } + // We need to reject methods that are not authenticated + // besides login and logout + if ( strcasecmp($this->params->action, 'logout') ) { + if ( !( $user and $user['Username'] ) ) { + throw new UnauthorizedException(__('Not Authenticated')); + return; + } else if ( !( $user and $user['Enabled'] ) ) { + throw new UnauthorizedException(__('User is not enabled')); + return; + } + } # end if ! login or logout + } # end if ZM_OPT_AUTH + } # end function beforeFilter() } diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php index 6b89d7c50..1d9456cc4 100644 --- a/web/api/app/Controller/EventsController.php +++ b/web/api/app/Controller/EventsController.php @@ -1,5 +1,6 @@ Session->Read('eventPermission'); - if ( $canView == 'None' ) { + global $user; + $canView = (!$user) || ($user['Events'] != 'None'); + if ( !$canView ) { throw new UnauthorizedException(__('Insufficient Privileges')); return; } @@ -32,15 +34,16 @@ class EventsController extends AppController { public function index() { $this->Event->recursive = -1; - $allowedMonitors = preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); + global $user; + $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null; - if ( !empty($allowedMonitors) ) { + if ( $allowedMonitors ) { $mon_options = array('Event.MonitorId' => $allowedMonitors); } else { $mon_options = ''; } - if ( $this->request->params['named'] ) { + if ( $this->request->params['named'] ) { //$this->FilterComponent = $this->Components->load('Filter'); //$conditions = $this->FilterComponent->buildFilter($this->request->params['named']); $conditions = $this->request->params['named']; @@ -85,13 +88,13 @@ class EventsController extends AppController { $events = $this->Paginator->paginate('Event'); // For each event, get the frameID which has the largest score - foreach ($events as $key => $value) { + foreach ( $events as $key => $value ) { $maxScoreFrameId = $this->getMaxScoreAlarmFrameId($value['Event']['Id']); $events[$key]['Event']['MaxScoreFrameId'] = $maxScoreFrameId; } $this->set(compact('events')); - } + } // end public function index() /** * view method @@ -108,9 +111,10 @@ class EventsController extends AppController { throw new NotFoundException(__('Invalid event')); } - $allowedMonitors = preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); + global $user; + $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null; - if ( !empty($allowedMonitors) ) { + if ( $allowedMonitors ) { $mon_options = array('Event.MonitorId' => $allowedMonitors); } else { $mon_options = ''; @@ -149,7 +153,9 @@ class EventsController extends AppController { */ public function add() { - if ( $this->Session->Read('eventPermission') != 'Edit' ) { + global $user; + $canEdit = (!$user) || ($user['Events'] == 'Edit'); + if ( !$canEdit ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -173,7 +179,9 @@ class EventsController extends AppController { */ public function edit($id = null) { - if ( $this->Session->Read('eventPermission') != 'Edit' ) { + global $user; + $canEdit = (!$user) || ($user['Events'] == 'Edit'); + if ( !$canEdit ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -204,7 +212,9 @@ class EventsController extends AppController { * @return void */ public function delete($id = null) { - if ( $this->Session->Read('eventPermission') != 'Edit' ) { + global $user; + $canEdit = (!$user) || ($user['Events'] == 'Edit'); + if ( !$canEdit ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -257,9 +267,9 @@ class EventsController extends AppController { $moreconditions = ''; foreach ($this->request->params['named'] as $name => $param) { $moreconditions = $moreconditions . ' AND '.$name.$param; - } + } - $query = $this->Event->query("select MonitorId, COUNT(*) AS Count from Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;"); + $query = $this->Event->query("SELECT MonitorId, COUNT(*) AS Count FROM Events WHERE (StartTime >= (DATE_SUB(NOW(), interval $interval)) $moreconditions) GROUP BY MonitorId;"); foreach ($query as $result) { $results[$result['Events']['MonitorId']] = $result[0]['Count']; @@ -336,7 +346,7 @@ class EventsController extends AppController { $thumbData['Width'] = (int)$thumbWidth; $thumbData['Height'] = (int)$thumbHeight; - return( $thumbData ); + return $thumbData; } public function archive($id = null) { diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php index 5b7c849fe..6dd9e5211 100644 --- a/web/api/app/Controller/HostController.php +++ b/web/api/app/Controller/HostController.php @@ -8,9 +8,9 @@ class HostController extends AppController { public function daemonCheck($daemon=false, $args=false) { $string = Configure::read('ZM_PATH_BIN').'/zmdc.pl check'; if ( $daemon ) { - $string .= " $daemon"; - if ( $args ) - $string .= " $args"; + $string .= " $daemon"; + if ( $args ) + $string .= " $args"; } $result = exec($string); $result = preg_match('/running/', $result); @@ -29,95 +29,9 @@ class HostController extends AppController { '_serialize' => array('load') )); } - - function login() { - $options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')); - $config = $this->Config->find('first', $options); - $zmOptAuth = $config['Config']['Value']; - - if ( $zmOptAuth == '1' ) { - - require_once "../../../includes/auth.php"; - global $user; - $user = $this->Session->read('user'); - - - - $mUser = $this->request->data('user'); - $mPassword = $this->request->data('pass'); - $mAuth = $this->request->data('auth'); - - - if ( $mUser and $mPassword) { - $user = userLogin($mUser, $mPassword); - if ( !$user ) { - throw new UnauthorizedException(__('User not found or incorrect password')); - return; - } - } - - elseif ( $mAuth ) { - $user = getAuthUser($mAuth); - if ( ! $user ) { - throw new UnauthorizedException(__('User not found or incorrect password')); - return; - } - } - else { - throw new UnauthorizedException(__('missing credentials')); - } - - if ( 0 and $user ) { - # We have to redo the session variables because cakephp's Session code will overwrite the normal php session - # Actually I'm not sure that is true. Getting indeterminate behaviour - Logger::Debug("user.Username: " . $this->Session->read('user.Username')); - if ( ! $this->Session->Write('user', $user) ) - $this->log("Error writing session var user"); - Logger::Debug("user.Username: " . $this->Session->read('user.Username')); - if ( ! $this->Session->Write('user.Username', $user['Username']) ) - $this->log("Error writing session var user.Username"); - if ( ! $this->Session->Write('password', $user['Password']) ) - $this->log("Error writing session var user.Username"); - if ( ! $this->Session->Write('user.Enabled', $user['Enabled']) ) - $this->log("Error writing session var user.Enabled"); - if ( ! $this->Session->Write('remoteAddr', $_SERVER['REMOTE_ADDR']) ) - $this->log("Error writing session var remoteAddr"); - } - - - - // I don't think this is really needed - the Username part - // Enabled check is ok - if ( !$user['Username'] ) { - throw new UnauthorizedException(__('Not Authenticated')); - return; - } else if ( !$user['Enabled'] ) { - throw new UnauthorizedException(__('User is not enabled')); - return; - } - - - $this->Session->Write('allowedMonitors',$user['MonitorIds']); - $this->Session->Write('streamPermission',$user['Stream']); - $this->Session->Write('eventPermission',$user['Events']); - $this->Session->Write('controlPermission',$user['Control']); - $this->Session->Write('systemPermission',$user['System']); - $this->Session->Write('monitorPermission',$user['Monitors']); - } else { - // if auth is not on, you can do everything - //$userMonitors = $this->User->find('first', $options); - $this->Session->Write('allowedMonitors',''); - $this->Session->Write('streamPermission','View'); - $this->Session->Write('eventPermission','Edit'); - $this->Session->Write('controlPermission','Edit'); - $this->Session->Write('systemPermission','Edit'); - $this->Session->Write('monitorPermission','Edit'); - } - - $cred = $this->_getCredentials(); $ver = $this->_getVersion(); $this->set(array( @@ -130,8 +44,7 @@ class HostController extends AppController { 'version', 'apiversion' ))); - - } + } // end function login() // clears out session function logout() { @@ -143,7 +56,7 @@ class HostController extends AppController { '_serialize' => array('result') )); - } + } // end function logout() private function _getCredentials() { $credentials = ''; @@ -167,8 +80,7 @@ class HostController extends AppController { } } return array($credentials, $appendPassword); - - } + } // end function _getCredentials function getCredentials() { // ignore debug warnings from other functions @@ -180,8 +92,6 @@ class HostController extends AppController { '_serialize' => array('credentials', 'append_password') ) ); } - - // If $mid is set, only return disk usage for that monitor // Else, return an array of total disk usage, and per-monitor diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 05756ede0..5ce4bb476 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -21,8 +21,10 @@ class MonitorsController extends AppController { public function beforeFilter() { parent::beforeFilter(); - $canView = $this->Session->Read('monitorPermission'); - if ($canView == 'None') { + global $user; + # We already tested for auth in appController, so we just need to test for specific permission + $canView = (!$user) || ($user['Monitors'] != 'None'); + if ( !$canView ) { throw new UnauthorizedException(__('Insufficient Privileges')); return; } @@ -44,8 +46,9 @@ class MonitorsController extends AppController { $conditions = array(); } - $allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); - if (!empty($allowedMonitors)) { + global $user; + $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null; + if ( $allowedMonitors ) { $conditions['Monitor.Id' ] = $allowedMonitors; } $find_array = array('conditions'=>$conditions,'contain'=>array('Group')); @@ -88,8 +91,9 @@ class MonitorsController extends AppController { if ( !$this->Monitor->exists($id) ) { throw new NotFoundException(__('Invalid monitor')); } - $allowedMonitors=preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); - if ( !empty($allowedMonitors) ) { + global $user; + $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'], NULL, PREG_SPLIT_NO_EMPTY) : null; + if ( $allowedMonitors ) { $restricted = array('Monitor.' . $this->Monitor->primaryKey => $allowedMonitors); } else { $restricted = ''; @@ -115,7 +119,9 @@ class MonitorsController extends AppController { public function add() { if ( $this->request->is('post') ) { - if ( $this->Session->Read('systemPermission') != 'Edit' ) { + global $user; + $canAdd = (!$user) || ($user['System'] == 'Edit' ); + if ( !$canAdd ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -148,7 +154,9 @@ class MonitorsController extends AppController { if ( !$this->Monitor->exists($id) ) { throw new NotFoundException(__('Invalid monitor')); } - if ( $this->Session->Read('monitorPermission') != 'Edit' ) { + global $user; + $canEdit = (!$user) || ($user['Monitors'] == 'Edit'); + if ( !$canEdit ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -215,7 +223,7 @@ class MonitorsController extends AppController { } public function sourceTypes() { - $sourceTypes = $this->Monitor->query("describe Monitors Type;"); + $sourceTypes = $this->Monitor->query('describe Monitors Type;'); preg_match('/^enum\((.*)\)$/', $sourceTypes[0]['COLUMNS']['Type'], $matches); foreach( explode(',', $matches[1]) as $value ) { @@ -264,7 +272,6 @@ class MonitorsController extends AppController { $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']; @@ -315,7 +322,7 @@ class MonitorsController extends AppController { $monitor = Set::extract('/Monitor/.', $monitor); // Pass -d for local, otherwise -m - if ($monitor[0]['Type'] == 'Local') { + if ( $monitor[0]['Type'] == 'Local' ) { $args = '-d '. $monitor[0]['Device']; } else { $args = '-m '. $monitor[0]['Id']; @@ -324,7 +331,7 @@ class MonitorsController extends AppController { // Build the command, and execute it $zm_path_bin = Configure::read('ZM_PATH_BIN'); $command = escapeshellcmd("$zm_path_bin/zmdc.pl status $daemon $args"); - $status = exec( $command ); + $status = exec($command); // If 'not' is present, the daemon is not running, so return false // https://github.com/ZoneMinder/ZoneMinder/issues/799#issuecomment-108996075 @@ -360,9 +367,9 @@ class MonitorsController extends AppController { $zm_path_bin = Configure::read('ZM_PATH_BIN'); - foreach ($daemons as $daemon) { + foreach ( $daemons as $daemon ) { $args = ''; - if ( $daemon == 'zmc' and $monitor['Type'] == 'Local') { + if ( $daemon == 'zmc' and $monitor['Type'] == 'Local' ) { $args = '-d ' . $monitor['Device']; } else { $args = '-m ' . $id; @@ -372,5 +379,4 @@ class MonitorsController extends AppController { $status = exec( $shellcmd ); } } - } // end class MonitorsController diff --git a/web/api/app/Controller/ServersController.php b/web/api/app/Controller/ServersController.php index 88a5bec90..c30de038f 100644 --- a/web/api/app/Controller/ServersController.php +++ b/web/api/app/Controller/ServersController.php @@ -8,7 +8,6 @@ App::uses('AppController', 'Controller'); */ class ServersController extends AppController { - /** * Components * @@ -16,18 +15,16 @@ class ServersController extends AppController { */ public $components = array('Paginator', 'RequestHandler'); - -public function beforeFilter() { - parent::beforeFilter(); - $canView = $this->Session->Read('streamPermission'); - if ($canView =='None') { - throw new UnauthorizedException(__('Insufficient Privileges')); - return; + public function beforeFilter() { + parent::beforeFilter(); + global $user; + $canView = (!$user) || ($user['System'] != 'None'); + if ( !$canView ) { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } } -} - - /** * index method * @@ -36,7 +33,7 @@ public function beforeFilter() { public function index() { $this->Server->recursive = 0; - $options=''; + $options = ''; $servers = $this->Server->find('all',$options); $this->set(array( 'servers' => $servers, @@ -76,16 +73,17 @@ public function beforeFilter() { * @return void */ public function add() { - if ($this->request->is('post')) { + if ( $this->request->is('post') ) { - if ($this->Session->Read('systemPermission') != 'Edit') - { - throw new UnauthorizedException(__('Insufficient privileges')); + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); return; } $this->Server->create(); - if ($this->Server->save($this->request->data)) { + 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')); @@ -103,15 +101,17 @@ public function beforeFilter() { 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')); + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); return; } - if ($this->Server->save($this->request->data)) { + + if ( !$this->Server->exists($id) ) { + throw new NotFoundException(__('Invalid server')); + } + if ( $this->Server->save($this->request->data) ) { $message = 'Saved'; } else { $message = 'Error'; @@ -133,20 +133,22 @@ public function beforeFilter() { * @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')); + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); return; } + + $this->Server->id = $id; + if ( !$this->Server->exists() ) { + throw new NotFoundException(__('Invalid server')); + } $this->request->allowMethod('post', 'delete'); #$this->daemonControl($this->Server->id, 'stop'); - if ($this->Server->delete()) { + 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/Controller/StatesController.php b/web/api/app/Controller/StatesController.php index 051837b27..29201d2c1 100644 --- a/web/api/app/Controller/StatesController.php +++ b/web/api/app/Controller/StatesController.php @@ -12,30 +12,28 @@ class StatesController extends AppController { public $components = array('RequestHandler'); public function beforeFilter() { - parent::beforeFilter(); - $canView = $this->Session->Read('systemPermission'); - if ($canView =='None') - { - throw new UnauthorizedException(__('Insufficient Privileges')); - return; - } - + parent::beforeFilter(); + global $user; + $canView = (!$user) || ($user['System'] != 'None'); + if ( !$canView ) { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } } - /** * index method * * @return void */ - public function index() { - $this->State->recursive = 0; - $states = $this->State->find('all'); - $this->set(array( - 'states' => $states, - '_serialize' => array('states') - )); - } +public function index() { + $this->State->recursive = 0; + $states = $this->State->find('all'); + $this->set(array( + 'states' => $states, + '_serialize' => array('states') + )); +} /** * view method @@ -44,35 +42,35 @@ public function beforeFilter() { * @param string $id * @return void */ - public function view($id = null) { - if (!$this->State->exists($id)) { - throw new NotFoundException(__('Invalid state')); - } - $options = array('conditions' => array('State.' . $this->State->primaryKey => $id)); - $this->set('state', $this->State->find('first', $options)); - } +public function view($id = null) { + if ( !$this->State->exists($id) ) { + throw new NotFoundException(__('Invalid state')); + } + $options = array('conditions' => array('State.' . $this->State->primaryKey => $id)); + $this->set('state', $this->State->find('first', $options)); +} /** * add method * * @return void */ - public function add() { - - if ($this->request->is('post')) { +public function add() { - if ($this->Session->Read('systemPermission') != 'Edit') - { - throw new UnauthorizedException(__('Insufficient privileges')); - return; - } + if ($this->request->is('post')) { - $this->State->create(); - if ($this->State->save($this->request->data)) { - return $this->flash(__('The state has been saved.'), array('action' => 'index')); - } - } - } + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + + $this->State->create(); + if ($this->State->save($this->request->data)) { + return $this->flash(__('The state has been saved.'), array('action' => 'index')); + } + } +} /** * edit method @@ -81,26 +79,27 @@ public function beforeFilter() { * @param string $id * @return void */ - public function edit($id = null) { - if (!$this->State->exists($id)) { - throw new NotFoundException(__('Invalid state')); - } +public function edit($id = null) { + if (!$this->State->exists($id)) { + throw new NotFoundException(__('Invalid state')); + } - if ($this->Session->Read('systemPermission') != 'Edit') - { - throw new UnauthorizedException(__('Insufficient privileges')); - return; - } + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } - if ($this->request->is(array('post', 'put'))) { - if ($this->State->save($this->request->data)) { - return $this->flash(__('The state has been saved.'), array('action' => 'index')); - } - } else { - $options = array('conditions' => array('State.' . $this->State->primaryKey => $id)); - $this->request->data = $this->State->find('first', $options); - } - } + if ( $this->request->is(array('post', 'put')) ) { + if ( $this->State->save($this->request->data) ) { + return $this->flash(__('The state has been saved.'), array('action' => 'index')); + } + } else { + $options = array('conditions' => array('State.' . $this->State->primaryKey => $id)); + $this->request->data = $this->State->find('first', $options); + } +} /** * delete method @@ -109,48 +108,50 @@ public function beforeFilter() { * @param string $id * @return void */ - public function delete($id = null) { - $this->State->id = $id; - if ($this->Session->Read('systemPermission') != 'Edit') - { - throw new UnauthorizedException(__('Insufficient privileges')); - return; - } +public function delete($id = null) { + $this->State->id = $id; + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } - if (!$this->State->exists()) { - throw new NotFoundException(__('Invalid state')); - } - $this->request->allowMethod('post', 'delete'); - if ($this->State->delete()) { - return $this->flash(__('The state has been deleted.'), array('action' => 'index')); - } else { - return $this->flash(__('The state could not be deleted. Please, try again.'), array('action' => 'index')); - } - } + if (!$this->State->exists()) { + throw new NotFoundException(__('Invalid state')); + } + $this->request->allowMethod('post', 'delete'); + if ($this->State->delete()) { + return $this->flash(__('The state has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The state could not be deleted. Please, try again.'), array('action' => 'index')); + } +} - public function change() { - if ($this->Session->Read('systemPermission') != 'Edit') - { - throw new UnauthorizedException(__('Insufficient privileges')); - return; - } +public function change() { + global $user; + $canEdit = (!$user) || ($user['System'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } - $newState = $this->request->params['pass'][0]; - $blah = $this->packageControl($newState); + $newState = $this->request->params['pass'][0]; + $blah = $this->packageControl($newState); - $this->set(array( - 'blah' => $blah, - '_serialize' => array('blah') - )); - } + $this->set(array( + 'blah' => $blah, + '_serialize' => array('blah') + )); +} - public function packageControl( $command ) { - $zm_path_bin = Configure::read('ZM_PATH_BIN'); - $string = $zm_path_bin.'/zmpkg.pl '.escapeshellarg( $command ); - $status = exec( $string ); +public function packageControl( $command ) { + $zm_path_bin = Configure::read('ZM_PATH_BIN'); + $string = $zm_path_bin.'/zmpkg.pl '.escapeshellarg( $command ); + $status = exec( $string ); - return $status; - } + return $status; +} } diff --git a/web/api/app/Controller/ZonesController.php b/web/api/app/Controller/ZonesController.php index 64cd7b144..74a87f353 100644 --- a/web/api/app/Controller/ZonesController.php +++ b/web/api/app/Controller/ZonesController.php @@ -16,8 +16,10 @@ class ZonesController extends AppController { public function beforeFilter() { parent::beforeFilter(); - $canView = $this->Session->Read('monitorPermission'); - if ( $canView =='None' ) { + + global $user; + $canView = (!$user) || $user['Monitors'] != 'None'; + if ( !$canView ) { throw new UnauthorizedException(__('Insufficient Privileges')); return; } @@ -38,12 +40,12 @@ class ZonesController extends AppController { '_serialize' => array('zones') )); } - public function index() { $this->Zone->recursive = -1; - $allowedMonitors = preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); - if ( !empty($allowedMonitors) ) { + global $user; + $allowedMonitors = $user ? preg_split('@,@', $user['MonitorIds'],NULL, PREG_SPLIT_NO_EMPTY) : null; + if ( $allowedMonitors ) { $mon_options = array('Zones.MonitorId' => $allowedMonitors); } else { $mon_options = ''; @@ -62,6 +64,14 @@ class ZonesController extends AppController { */ public function add() { if ( $this->request->is('post') ) { + + global $user; + $canEdit = (!$user) || $user['Monitors'] == 'Edit'; + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } + $this->Zone->create(); if ( $this->Zone->save($this->request->data) ) { return $this->flash(__('The zone has been saved.'), array('action' => 'index')); @@ -85,6 +95,12 @@ class ZonesController extends AppController { throw new NotFoundException(__('Invalid zone')); } if ( $this->request->is(array('post', 'put')) ) { + global $user; + $canEdit = (!$user) || $user['Monitors'] == 'Edit'; + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } if ( $this->Zone->save($this->request->data) ) { return $this->flash(__('The zone has been saved.'), array('action' => 'index')); } @@ -109,6 +125,12 @@ class ZonesController extends AppController { throw new NotFoundException(__('Invalid zone')); } $this->request->allowMethod('post', 'delete'); + global $user; + $canEdit = (!$user) || $user['Monitors'] == 'Edit'; + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } if ( $this->Zone->delete() ) { return $this->flash(__('The zone has been deleted.'), array('action' => 'index')); } else { @@ -144,4 +166,4 @@ class ZonesController extends AppController { '_serialize' => array('status') )); } -} +} // end class From d87a41b6295c23d95170492a9c456bcc7c916052 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 8 Aug 2018 15:11:30 -0400 Subject: [PATCH 16/52] Set button types so that they do things in all browsers.Fix Delete button when translated --- web/skins/classic/views/filter.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 675a178bf..d573c9d56 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -410,22 +410,22 @@ if ( ZM_OPT_MESSAGE ) {
- - + + - - + + Id() ) { ?> - + - +
From 3dc424282b60ae10ea9f0bde1d36579a1e27e977 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 11 Aug 2018 11:56:16 -0500 Subject: [PATCH 17/52] Support quoting config variables (#2175) * allow handling of quotes in config files * copy paste error * surround zm_arptool in quotes --- conf.d/01-system-paths.conf.in | 2 +- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 2 +- src/zm_config.cpp | 7 ++++--- web/includes/config.php.in | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/conf.d/01-system-paths.conf.in b/conf.d/01-system-paths.conf.in index 9f45abdbd..e97433ba2 100644 --- a/conf.d/01-system-paths.conf.in +++ b/conf.d/01-system-paths.conf.in @@ -50,4 +50,4 @@ ZM_PATH_SWAP=@ZM_TMPDIR@ # Full path to optional arp binary # ZoneMinder will find the arp binary automatically on most systems -ZM_PATH_ARP=@ZM_PATH_ARP@ +ZM_PATH_ARP="@ZM_PATH_ARP@" diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 7a86b51a8..d48747703 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -149,7 +149,7 @@ BEGIN { foreach my $str ( <$CONFIG> ) { next if ( $str =~ /^\s*$/ ); next if ( $str =~ /^\s*#/ ); - my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.*?)\s*$/; + my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/; if ( ! $name ) { print( STDERR "Warning, bad line in $config_file: $str\n" ); next; diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 0865bc6e4..6d63be98b 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -123,9 +123,9 @@ void process_configfile( char* configFile) { if ( *line_ptr == '\0' || *line_ptr == '#' ) continue; - // Remove trailing white space + // Remove trailing white space and trailing quotes char *temp_ptr = line_ptr+strlen(line_ptr)-1; - while ( *temp_ptr == ' ' || *temp_ptr == '\t' ) { + while ( *temp_ptr == ' ' || *temp_ptr == '\t' || *temp_ptr == '\'' || *temp_ptr == '\"') { *temp_ptr-- = '\0'; temp_ptr--; } @@ -147,8 +147,9 @@ void process_configfile( char* configFile) { temp_ptr--; } while ( *temp_ptr == ' ' || *temp_ptr == '\t' ); - // Remove leading white space from the value part + // Remove leading white space and leading quotes from the value part white_len = strspn( val_ptr, " \t" ); + white_len += strspn( val_ptr, "\'\"" ); val_ptr += white_len; if ( strcasecmp( name_ptr, "ZM_DB_HOST" ) == 0 ) diff --git a/web/includes/config.php.in b/web/includes/config.php.in index c6aa93c63..a2a89b224 100644 --- a/web/includes/config.php.in +++ b/web/includes/config.php.in @@ -212,7 +212,7 @@ function process_configfile($configFile) { continue; elseif ( preg_match( '/^\s*#/', $str )) continue; - elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches )) + elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches )) $configvals[$matches[1]] = $matches[2]; } fclose( $cfg ); From e6d1a9447e360b83b06df81d072bf8549540814a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Aug 2018 11:12:15 -0400 Subject: [PATCH 18/52] rename TVIP862 to Trendnet and delete TVIP672WI --- .../lib/ZoneMinder/Control/TVIP672WI.pm | 590 ------------------ .../Control/{TVIP862.pm => Trendnet.pm} | 31 +- 2 files changed, 8 insertions(+), 613 deletions(-) delete mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm rename scripts/ZoneMinder/lib/ZoneMinder/Control/{TVIP862.pm => Trendnet.pm} (93%) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm deleted file mode 100644 index 4828b65b0..000000000 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP672WI.pm +++ /dev/null @@ -1,590 +0,0 @@ -# ========================================================================= -# -# ZoneMinder Trendnet TV-IP672WI IP Control Protocol Module, $Date: $, $Revision: $ -# Copyright (C) 2014 Vincent Giovannone -# Updated 2017 Michael Barkdoll -# -# -# ========================================================================== -# -# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ========================================================================== -# -# This module contains the implementation of the Trendnet TV-IP672WI IP camera control -# protocol. -# -# Tested on Zoneminder 1.30.4 -# -# Under control capability: -# -# * Main: name it (suggest TVIP672WI), type is FFMPEG (or remote if you're using MJPEG), protocol is TVIP672WI -# * Main (more): Can wake, can sleep, can reset -# * Move: Can move, can move diagonally, can move mapped, can move relative -# * Pan: Can pan -# * Tilt: Can tilt -# -# * Presets: Has presets, num presets 20, has home preset (don't set presets via camera's web server, only set via ZM.) -# (I didn't test/use presets -MB) -# -# Under control tab in the monitor itself: -# -# * Controllable -# * Control type is the name you gave it in control capability above -# * Control device is the username and password you use to authenticate to the camera -# E.g., admin:password -# -# * Control address is the camera's ip address AND web port -# E.g., 192.168.1.100:80 -# Optionally, it can parse all username and password with the following format: -# http://admin:password@192.168.1.100:80 -# -# -# If using with anything but a TV-IP672WI (ex: TV-IP672PI), YOU MUST MATCH THE REALM TO MATCH YOUR CAMERA FURTHER DOWN! -# -# -# Due to how the TVIP672 represents presets internally, you MUST define the presets in order... i.e. 1,2,3,4... not 1,10,3,4. -# (see much further down for why, if you care...) -# -# Install this file with the following commands: -# -# sudo cp TVIP672WI.pm /usr/share/perl5/ZoneMinder/Control/ -# sudo chmod 755 /usr/share/perl5/ZoneMinder/Control/TVIP672WI.pm - - -package ZoneMinder::Control::TVIP672WI; - -use 5.006; -use strict; -use warnings; - -require ZoneMinder::Base; -require ZoneMinder::Control; - -our @ISA = qw(ZoneMinder::Control); - -# -# ******** YOU MUST CHANGE THE FOLLOWING LINES TO MATCH YOUR CAMERA! ********** -# -# I assume that "TV-IP672WI" would work for the TV-IP672PI, but can't test since I don't own one. -# -# TV-IP672WI works for the WI version, of course. -# -# Finally, the username is the username you'd like to authenticate as. -# -#our $REALM = 'TV-IP862IC'; -#our $REALM = 'TV-IP672PI'; - -our $REALM = 'TV-IP672WI'; -#our $REALM = 'TVIP672WI'; - -# $USERNAME and $PASSWORD are parsed from ControlDevice field in GUI -# E.g., username:password -# Note: values defined below are overriden by GUI values -our $USERNAME = ''; -our $PASSWORD = ''; - -# $ADDRESS is parsed from field, 'Control Address' -our $ADDRESS = ''; - -# ========================================================================== -# -# Trendnet TV-IP672PI Control Protocol -# -# ========================================================================== - -use ZoneMinder::Logger qw(:all); -use ZoneMinder::Config qw(:all); - -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(); - - my $controldevice = $self->{Monitor}->{ControlDevice}; - if ( $controldevice && $controldevice =~ m/\:/ ) { - my ( $adminname, $lastpass ) - = split(/\:/, $controldevice, 2); - if ( $adminname ) { - $USERNAME = $adminname; - #Error( "Username updated to: " . $USERNAME ); - } - if ( $lastpass ) { - $PASSWORD = $lastpass; - #Error( "Password updated to: " . $PASSWORD ); - } - } else { - if ( $controldevice ) { - $PASSWORD = $controldevice; - #Error( "Password updated to: " . $PASSWORD ); - } else { - Error ( "Unable to parse Control Device field: " . $controldevice ); - } - } - - my ( $protocol, $username, $password, $address ) - = $self->{Monitor}->{ControlAddress} =~ /^(http?:\/\/)?([^:]+):([^\/@]+)@(.*)$/; - if ( ( $username ) && ( $password ) && ( $address ) ) { - $USERNAME = $username; - $PASSWORD = $password; - $ADDRESS = $address; - #Error( "Set USERNAME: " . $USERNAME . "PASSWORD: " . $PASSWORD . "ADDRESS: " . $ADDRESS ); - } else { - if ( ! ( $controldevice ) ) { - Error( "Failed to parse auth from address"); - Error( "Unable to pull username and password for authentication from fields ControlAddress or ControlDevice" ); - Error( "Control script attempts to pull these values from field ControlDevice as username:password" ); - Error( "Optionally, these values can also be set at /usr/share/perl5/ZoneMinder/Control/TVIP672WI.pm" ); - } - $ADDRESS = $self->{Monitor}->{ControlAddress}; - } - if ( ! ( $ADDRESS =~ m/\:/ ) ) { - $ADDRESS .= ':80'; - Debug( "You generally need to also specify the port. I will append :80" ); - } - - Debug ( "Address is now: " . $ADDRESS ); - - use LWP::UserAgent; - use HTTP::Request::Common; - $self->{ua} = LWP::UserAgent->new; - $self->{ua}->agent( "ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION ); - $self->{state} = 'open'; - # credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string) - $self->{ua}->credentials($ADDRESS,$REALM,$USERNAME,$PASSWORD); - -# Detect REALM - my $req = HTTP::Request->new( GET=>"http://".$ADDRESS."/cgi/ptdc.cgi" ); - my $res = $self->{ua}->request($req); - - if ( ! $res->is_success ) { - Debug("Need newer REALM"); - - if ( $res->status_line() eq '401 Unauthorized' ) { - my $headers = $res->headers(); - foreach my $k ( keys %$headers ) { - Error("Initial Header $k => $$headers{$k}"); - } # end foreach - if ( $$headers{'www-authenticate'} ) { - my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/; - if ( $tokens =~ /\w+="([^"]+)"/i ) { - $REALM = $1; - Debug( "Changing REALM to $REALM" ); - $self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD); - my $req = HTTP::Request->new( GET=>"http://".$ADDRESS."/cgi/ptdc.cgi" ); - my $res = $self->{ua}->request($req); - if ( ! $res->is_success ) { - Error ( "Unable to authenticate!!!" ); - } - } # end if - } else { - Error("No headers line"); - } # end if headers - } # end if $res->status_line() eq '401 Unauthorized' - } # end if ! $res->is_success -} - -sub close -{ - my $self = shift; - $self->{state} = 'closed'; -} - -sub printMsg -{ - my $self = shift; - my $msg = shift; - my $msg_len = length($msg); - - Debug( $msg."[".$msg_len."]" ); -} - -sub sendCmd -{ - -# This routine is used for all moving, which are all GET commands... - - my $self = shift; - my $cmd = shift; - - my $result = undef; - - # Assuming you've placed your camera on a secure vlan network for ip cameras... - my $url = "http://".$USERNAME.":".$PASSWORD."@".$ADDRESS."/cgi/ptdc.cgi?command=".$cmd; - # The following didn't work with the TV-IP672WI; required authentication despite previous auth - #my $url = "http://".$ADDRESS."/cgi/ptdc.cgi?command=".$cmd; - my $req = HTTP::Request->new( GET=>$url ); - - Debug ("sendCmd command: " . $url ); - - my $res = $self->{ua}->request($req); - - if ( $res->is_success ) { - $result = !undef; - } else { - if ( $res->status_line() eq '401 Unauthorized' ) { - Debug( "Error check failed, trying again: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); - Debug("Content was " . $res->content() ); - my $res = $self->{ua}->request($req); - if ( $res->is_success ) { - $result = !undef; - } else { - Debug("Content was " . $res->content() ); - } - } - if ( ! $result ) { - Debug( "Error check failed: '".$res->status_line()."' cmd:'".$cmd."'" ); - } - } - - return( $result ); -} - - - -sub sendCmdPost -{ - -# -# This routine is used for setting/clearing presets and IR commands, which are POST commands... -# - - my $self = shift; - my $url = shift; - my $cmd = shift; - - my $result = undef; - - if ($url eq undef) - { - Error ("url passed to sendCmdPost is undefined."); - return(-1); - } - - Debug ("sendCmdPost url: " . $url . " cmd: " . $cmd); - - my $req = HTTP::Request->new(POST => "http://".$ADDRESS.$url); - $req->content_type('application/x-www-form-urlencoded'); - $req->content($cmd); - - Debug ( "sendCmdPost credentials control address:'".$ADDRESS."' realm:'" . $REALM . "' username:'" . $USERNAME . "' password:'".$PASSWORD."'"); - - my $res = $self->{ua}->request($req); - - if ( $res->is_success ) - { - $result = !undef; - } - else - { - Error( "sendCmdPost Error check failed: '".$res->status_line()."' cmd:'".$cmd."'" ); - if ( $res->status_line() eq '401 Unauthorized' ) { - Error( "sendCmdPost Error check failed: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); - } else { - Error( "sendCmdPost Error check failed: USERNAME: $USERNAME realm: $REALM password: " . $PASSWORD ); - } # endif - } - - return( $result ); -} - - - -sub move -{ - my $self = shift; - my $panSteps = shift; - my $tiltSteps = shift; - - my $cmd = "set_relative_pos&posX=$panSteps&posY=$tiltSteps"; - $self->sendCmd( $cmd ); -} - -sub moveRelUpLeft -{ - my $self = shift; - Debug( "Move Up Left" ); - $self->move(-3, 3); -} - -sub moveRelUp -{ - my $self = shift; - Debug( "Move Up" ); - $self->move(0, 3); -} - -sub moveRelUpRight -{ - my $self = shift; - Debug( "Move Up Right" ); - $self->move(3, 3); -} - -sub moveRelLeft -{ - my $self = shift; - Debug( "Move Left" ); - $self->move(-3, 0); -} - -sub moveRelRight -{ - my $self = shift; - Debug( "Move Right" ); - $self->move(3, 0); -} - -sub moveRelDownLeft -{ - my $self = shift; - Debug( "Move Down Left" ); - $self->move(-3, -3); -} - -sub moveRelDown -{ - my $self = shift; - Debug( "Move Down" ); - $self->move(0, -3); -} - -sub moveRelDownRight -{ - my $self = shift; - Debug( "Move Down Right" ); - $self->move(3, -3); -} - - -# moves the camera to center on the point that the user clicked on in the video image. -# This isn't mega accurate but good enough for most purposes - -sub moveMap -{ - - # If the camera moves too much, increase hscale and vscale. (...if it doesn't move enough, try decreasing!) - # They scale the movement and are here to compensate for manufacturing variation. - # It's never going to be perfect, so just get somewhere in the ballpark and call it a day. - # (Don't forget to kill the zmcontrol process while tweaking!) - - # 1280x800 - my $hscale = 31; - my $vscale = 25; - - # 1280x800 with fisheye - #my $hscale = 15; - #my $vscale = 15; - - # 640x400 - #my $hscale = 14; - #my $vscale = 12; - - - my $self = shift; - my $params = shift; - my $xcoord = $self->getParam( $params, 'xcoord' ); - my $ycoord = $self->getParam( $params, 'ycoord' ); - - my $hor = ($xcoord - ($self->{Monitor}->{Width} / 2))/$hscale; - my $ver = ($ycoord - ($self->{Monitor}->{Height} / 2))/$vscale; - - $hor = int($hor); - $ver = -1 * int($ver); - - Debug( "Move Map to $xcoord,$ycoord, hor=$hor, ver=$ver" ); - $self->move( $hor, $ver ); -} - - -# **** PRESETS **** -# -# OK, presets work a little funky but they DO work, provided you define them in order and don't skip any. -# -# The problem is that when you load the web page for this camera, it gives a list of preset names tied to index numbers. -# So let's say you have four presets... A, B, C, and D, and defined them in that order. -# So A is index 0, B is index 1, C is index 2, D is index 3. When you tell the camera to go to a preset, you actually tell it by number, not by name. -# (So "Go to D" is really "go to index 3".) -# -# Now let's say somebody deletes C via the camera's web GUI. The camera re-numbers the existing presets A=0, B=1, D=2. -# There's really no easy way for ZM to discover this re-numbering, so zoneminder would still send "go to preset 3" thinking -# it's telling the camera to go to point D. In actuality it's telling the camera to go to a preset that no longer exists. -# -# As long as you define your presets in order (i.e. define preset 1, then preset 2, then preset 3, etc.) everything will work just -# fine in ZoneMinder. -# -# (Home preset needs to be set via the camera's web gui, and is unaffected by any of this.) -# -# So that's the limitation: DEFINE YOUR PRESETS IN ORDER THROUGH (and only through!) ZM AND DON'T SKIP ANY. -# - - -sub presetClear -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - my $cmd = "presetName=$preset&command=del"; - my $url = "/eng/admin/cam_control.cgi"; - Debug ("presetClear: " . $preset . " cmd: " . $cmd); - $self->sendCmdPost($url,$cmd); -} - - -sub presetSet -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - my $cmd = "presetName=$preset&command=add"; - my $url = "/eng/admin/cam_control.cgi"; - Debug ("presetSet " . $preset . " cmd: " . $cmd); - $self->sendCmdPost ($url,$cmd); -} - -sub presetGoto -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - $preset = $preset - 1; - Debug( "Goto Preset $preset" ); - my $cmd = "goto_preset_position&index=$preset"; - $self->sendCmd( $cmd ); -} - -sub presetHome -{ - my $self = shift; - Debug( "Home Preset" ); - my $cmd = "go_home"; - $self->sendCmd( $cmd ); -} - - -# -# **** IR CONTROLS **** -# -# -# Wake: Force IR on, always. (always night mode) -# -# Sleep: Force IR off, always. (always day mode) -# -# Reset: Automatic IR mode. (day/night mode determined by camera) -# - - -sub wake -{ - # force IR on ("always night mode") - - my $self = shift; - my $url = "/eng/admin/adv_audiovideo.cgi"; - my $cmd = "irMode=3"; - - Debug("Wake -- IR on"); - - $self->sendCmdPost ($url,$cmd); -} - -sub sleep -{ - # force IR off ("always day mode") - - my $self=shift; - my $url = "/eng/admin/adv_audiovideo.cgi"; - my $cmd = "irMode=2"; - - Debug("Sleep -- IR off"); - - $self->sendCmdPost ($url,$cmd); -} - -sub reset -{ - # IR auto - - my $self=shift; - my $url = "/eng/admin/adv_audiovideo.cgi"; - my $cmd = "irMode=0"; - - Debug("Reset -- IR auto"); - - $self->sendCmdPost ($url,$cmd); -} - - -1; -__END__ -# Below is stub documentation for your module. You'd better edit it! - -=head1 NAME - -ZoneMinder::Database - Perl extension for Trendnet TVIP672 - -=head1 SYNOPSIS - - use ZoneMinder::Database; - stuff this in /usr/share/perl5/ZoneMinder/Control , then eat a sandwich - -=head1 DESCRIPTION - -Stub documentation for Trendnet TVIP672, created by Vince, updated by Michael. - -=head2 EXPORT - -None by default. - - - -=head1 SEE ALSO - -Read the comments at the beginning of this file to see the usage for zoneminder 1.25.0 - - -=head1 AUTHOR - -Vincent Giovannone, I'd rather you not email me; sure no problem... - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2014 by Vincent Giovannone - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.3 or, -at your option, any later version of Perl 5 you may have available. - - -=cut \ No newline at end of file diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP862.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm similarity index 93% rename from scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP862.pm rename to scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm index ec6e5a95e..a30aaaf46 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/TVIP862.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm @@ -1,7 +1,7 @@ #=========================================================================== # -# ZoneMinder Trendnet TV-IP862IC IP Control Protocol Module, $Date: $, $Revision: $ -# Copyright (C) 2014 Vincent Giovannone +# ZoneMinder Trendnet IP Control Protocol Module, $Date: $, $Revision: $ +# Copyright (C) 2018 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC # # # ========================================================================== @@ -18,12 +18,11 @@ # ========================================================================== # # This module contains the implementation of the Trendnet # IP camera control -# protocol. Has been testing with TV-IP862IC and TV-IP672PI +# protocol. Has been tested with TV-IP862IC # # Under control capability: # -# * Main: name it (suggest TVIP672PI), type is FFMPEG (or remote if you're using MJPEG), protocol is TVIP672PI -# * Main (more): Can wake, can sleep, can reset +# * Main: Can wake, can sleep, can reset # * Move: Can move, can move diagonally, can move mapped, can move relative # * Pan: Can pan # * Tilt: Can tilt @@ -37,12 +36,8 @@ # You can also put the authentication information here and change the # protocol to https using something like https://admin:password@192.168.1.1:80 # -# -# Due to how the TVIP672 represents presets internally, you MUST define the presets in order... i.e. 1,2,3,4... not 1,10,3,4. -# (see much further down for why, if you care...) -# -package ZoneMinder::Control::TVIP862; +package ZoneMinder::Control::Trendnet; use 5.006; use strict; @@ -62,7 +57,7 @@ our @ISA = qw(ZoneMinder::Control); # The username and password should be passed in the ControlDevice field but you # can set them here if you want. # -our $REALM = 'TV-IP862IC'; +our $REALM = ''; our $PROTOCOL = 'http://'; our $USERNAME = 'admin'; our $PASSWORD = ''; @@ -431,7 +426,7 @@ __END__ =head1 NAME -ZoneMinder::Database - Perl extension for Trendnet TVIP672 +ZoneMinder::Control::Trendnet - Perl module for Trendnet cameras =head1 SYNOPSIS @@ -440,22 +435,12 @@ ZoneMinder::Database - Perl extension for Trendnet TVIP672 =head1 DESCRIPTION -Stub documentation for Trendnet TVIP672, created by Vince. +Stub documentation for Trendnet PTZ Sctrol =head2 EXPORT None by default. - - -=head1 SEE ALSO - -Read the comments at the beginning of this file to see the usage for zoneminder 1.25.0 - - -=head1 AUTHOR - - =head1 COPYRIGHT AND LICENSE Copyright (C) 2018 by ZoneMinder LLC From 56f4d768c2783081e5918f9c5128a1b630d67c2c Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 13 Aug 2018 14:23:44 -0500 Subject: [PATCH 19/52] Add Privacy Statement (#2176) * initial implementation of privacy popup * split the privacy text and run it through translate * change style of toggle button, validate the form * fix copy/paste error * fix typos * display privacy view inline rather than popup * display privacy inline if show_privacy flag set * redirect to console after selection is made * typo * css formatting * update privacy verbiage * push privacy text to all language files --- .../lib/ZoneMinder/ConfigData.pm.in | 9 +++ scripts/zmupdate.pl.in | 5 ++ web/includes/actions.php | 25 ++++++- web/index.php | 5 ++ web/lang/big5_big5.php | 12 +++ web/lang/cn_zh.php | 12 +++ web/lang/cs_cz.php | 12 +++ web/lang/de_de.php | 12 +++ web/lang/dk_dk.php | 12 +++ web/lang/en_gb.php | 16 +++- web/lang/es_ar.php | 12 +++ web/lang/es_es.php | 12 +++ web/lang/et_ee.php | 12 +++ web/lang/fr_fr.php | 12 +++ web/lang/he_il.php | 12 +++ web/lang/hu_hu.php | 12 +++ web/lang/it_it.php | 12 +++ web/lang/ja_jp.php | 12 +++ web/lang/nl_nl.php | 12 +++ web/lang/pl_pl.php | 12 +++ web/lang/pt_br.php | 12 +++ web/lang/ro_ro.php | 12 +++ web/lang/ru_ru.php | 12 +++ web/lang/se_se.php | 12 +++ web/skins/classic/css/base/views/privacy.css | 14 ++++ web/skins/classic/views/js/privacy.js | 9 +++ web/skins/classic/views/privacy.php | 74 +++++++++++++++++++ 27 files changed, 382 insertions(+), 3 deletions(-) create mode 100644 web/skins/classic/css/base/views/privacy.css create mode 100644 web/skins/classic/views/js/privacy.js create mode 100644 web/skins/classic/views/privacy.php diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index c6136717a..6a3a66dae 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -3882,6 +3882,15 @@ our @options = ( readonly => 1, category => 'dynamic', }, + { + name => 'ZM_SHOW_PRIVACY', + default => 'yes', + description => 'Present the privacy statment', + help => '', + type => $types{boolean}, + readonly => 1, + category => 'dynamic', + }, { name => 'ZM_SSMTP_MAIL', default => 'no', diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index f428ea1f9..45d45851a 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -922,6 +922,11 @@ if ( $version ) { zmDbDisconnect(); die( "Can't find upgrade from version '$version'" ); } + # Re-enable the privacy popup after each upgrade + my $sql = "update Config set Value = 1 where Name = 'ZM_SHOW_PRIVACY'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() ); + $sth->finish(); print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" ); } zmDbDisconnect(); diff --git a/web/includes/actions.php b/web/includes/actions.php index a38515f3d..2f5df5823 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -547,7 +547,7 @@ if ( canEdit( 'Monitors' ) ) { $maxSeq = dbFetchOne('SELECT MAX(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence'); $changes[] = 'Sequence = '.($maxSeq+1); - if ( dbQuery( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ) ) { + if ( dbQuery/usr/share/zoneminder/www/lang/en_gb.php( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ) ) { $mid = dbInsertId(); $zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height']; dbQuery( "insert into Zones set MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) ); @@ -863,6 +863,29 @@ if ( canEdit( 'System' ) ) { } } // end switch option } + if ( $action == 'privacy' && isset($_REQUEST['option'] ) ) { + $option = $_REQUEST['option']; + switch( $option ) { + case 'decline' : + { + dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); + dbQuery( "update Config set Value = '0' where Name = 'ZM_TELEMETRY_DATA'" ); + $view = 'console'; + $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; + break; + } + case 'accept' : + { + dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); + dbQuery( "update Config set Value = '1' where Name = 'ZM_TELEMETRY_DATA'" ); + $view = 'console'; + $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; + break; + } + default: # Enable the privacy statement if we somehow submit something other than accept or decline + dbQuery( "update Config set Value = '1' where Name = 'ZM_SHOW_PRIVACY'" ); + } // end switch option + } if ( $action == 'options' && isset($_REQUEST['tab']) ) { $configCat = $configCats[$_REQUEST['tab']]; $changed = false; diff --git a/web/index.php b/web/index.php index 7f823f1fd..69745ce3c 100644 --- a/web/index.php +++ b/web/index.php @@ -221,6 +221,11 @@ if ( ZM_OPT_USE_AUTH and ! isset($user) ) { $request = null; } +if ( ZM_SHOW_PRIVACY && canEdit('System') ) { + Logger::Debug("Redirecting to privacy" ); + $view = 'privacy'; + $request = null; +} if ( $redirect ) { header('Location: '.$redirect); diff --git a/web/lang/big5_big5.php b/web/lang/big5_big5.php index b8bc173a5..b2e21264b 100644 --- a/web/lang/big5_big5.php +++ b/web/lang/big5_big5.php @@ -573,6 +573,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => '上一事件', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/cn_zh.php b/web/lang/cn_zh.php index 9ed821417..39206d038 100644 --- a/web/lang/cn_zh.php +++ b/web/lang/cn_zh.php @@ -569,6 +569,18 @@ $SLANG = array( 'Preset' => '预置', 'Presets' => '预置', 'Prev' => '前', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/cs_cz.php b/web/lang/cs_cz.php index adcdeb61d..228c2618d 100644 --- a/web/lang/cs_cz.php +++ b/web/lang/cs_cz.php @@ -569,6 +569,18 @@ $SLANG = array( 'Preset' => 'Předvolba', 'Presets' => 'Předvolby', 'Prev' => 'Zpět', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/de_de.php b/web/lang/de_de.php index 424d91e94..18a4e9cfe 100644 --- a/web/lang/de_de.php +++ b/web/lang/de_de.php @@ -572,6 +572,18 @@ $SLANG = array( 'Presets' => 'Voreinstellungen', 'Prev' => 'Vorheriges', 'Probe' => 'Suchen', // Added - 2009-03-31 + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'ProfileProbe' => 'Streamsonde', // Added - 2015-04-18 'ProfileProbeIntro' => 'Die folgende Liste zeigt die verfügbaren Streamingprofile der ausgewählten Kamera.

Wähle den gewünschten Eintrag aus der folgenden Liste.

Bitte Beachten: Zoneminder kann keine zusätzlichen Profile konfigurieren. Die Auswahl einer Kamera kann bereits eingetragene Werte im aktuellen Monitor überschreiben.

', // Added - 2015-04-18 'Progress' => 'Fortschritt', // Added - 2015-04-18 diff --git a/web/lang/dk_dk.php b/web/lang/dk_dk.php index 605f9fb19..b0c066237 100644 --- a/web/lang/dk_dk.php +++ b/web/lang/dk_dk.php @@ -580,6 +580,18 @@ $SLANG = array( 'Preset' => 'Forudindstilling', 'Presets' => 'Forudindstillinger', 'Prev' => 'Forrige', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', 'ProfileProbe' => 'Stream Probe', 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index ba77b156e..bb4fe9b26 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -600,6 +600,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Prev', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', 'ProfileProbe' => 'Stream Probe', 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', @@ -654,7 +666,7 @@ $SLANG = array( 'Select' => 'Select', 'SelectFormat' => 'Select Format', 'SelectLog' => 'Select Log', - 'SelfIntersecting' => 'Polygon edges must not intersect', + 'SelfIntersecting' => 'P/usr/share/zoneminder/www/lang/en_gb.phpolygon edges must not intersect', 'SetNewBandwidth' => 'Set New Bandwidth', 'SetPreset' => 'Set Preset', 'Set' => 'Set', @@ -662,7 +674,7 @@ $SLANG = array( 'ShowFilterWindow' => 'Show Filter Window', 'ShowTimeline' => 'Show Timeline', 'SignalCheckColour' => 'Signal Check Colour', - 'SignalCheckPoints' => 'Signal Check Points', + 'SignalCheckPoints' => 'S/usr/share/zoneminder/www/lang/en_gb.phpignal Check Points', 'Size' => 'Size', 'SkinDescription' => 'Change the skin for this session', 'CSSDescription' => 'Change the css for this session', diff --git a/web/lang/es_ar.php b/web/lang/es_ar.php index cbb3c2d88..0cb51c27b 100644 --- a/web/lang/es_ar.php +++ b/web/lang/es_ar.php @@ -520,6 +520,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Prev', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/es_es.php b/web/lang/es_es.php index 3e27d0fae..0397b9ea0 100644 --- a/web/lang/es_es.php +++ b/web/lang/es_es.php @@ -569,6 +569,18 @@ $SLANG = array( 'Preset' => 'Programa', 'Presets' => 'Programas', 'Prev' => 'Anterior', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Sondear', 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/et_ee.php b/web/lang/et_ee.php index 250728550..92360a20b 100644 --- a/web/lang/et_ee.php +++ b/web/lang/et_ee.php @@ -576,6 +576,18 @@ $SLANG = array( 'Preset' => 'Eelseatud', 'Presets' => 'Eelseaded', 'Prev' => 'Prev', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/fr_fr.php b/web/lang/fr_fr.php index b140886fe..227adf0e9 100644 --- a/web/lang/fr_fr.php +++ b/web/lang/fr_fr.php @@ -575,6 +575,18 @@ $SLANG = array( 'Preset' => 'Préréglage', 'Presets' => 'Préréglages', 'Prev' => 'Précédent', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Autodétection', // Added - 2009-03-31 'ProfileProbe' => 'Détection de flux', // Added - 2015-04-18 'ProfileProbeIntro' => 'La liste ci-dessous montre les profils de flux existants pour la caméra sélectionnée.

Sélectionnez le profil désiré dans la liste ci-dessous.

Veuillez noter que ZoneMinder ne peut pas configurer de profils additionels et que la sauvegarde entraînera l\'écrasement des paramètres déjà configurés pour la caméra en cours.

', // Added - 2015-04-18 diff --git a/web/lang/he_il.php b/web/lang/he_il.php index f8c8897a4..958b8e57f 100644 --- a/web/lang/he_il.php +++ b/web/lang/he_il.php @@ -569,6 +569,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'ä÷åãí', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/hu_hu.php b/web/lang/hu_hu.php index 3f0928be1..fe347fae7 100644 --- a/web/lang/hu_hu.php +++ b/web/lang/hu_hu.php @@ -612,6 +612,18 @@ $SLANG = array( 'Preset' => 'Előre beállított profil', 'Presets' => 'Előre beállított profilok', 'Prev' => 'Előző', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Érzékelés', 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/it_it.php b/web/lang/it_it.php index 338f2c07f..fe2e24bb7 100644 --- a/web/lang/it_it.php +++ b/web/lang/it_it.php @@ -574,6 +574,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Prec', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Prova la telecamera', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/ja_jp.php b/web/lang/ja_jp.php index 340d2caac..33d797725 100644 --- a/web/lang/ja_jp.php +++ b/web/lang/ja_jp.php @@ -570,6 +570,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => '前', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/nl_nl.php b/web/lang/nl_nl.php index fca70a829..87ab57c70 100644 --- a/web/lang/nl_nl.php +++ b/web/lang/nl_nl.php @@ -570,6 +570,18 @@ $SLANG = array( 'Preset' => 'Voorkeur', 'Presets' => 'Voorkeuren', 'Prev' => 'Vorige', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Scan', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/pl_pl.php b/web/lang/pl_pl.php index 325c2e1b9..1b4883db7 100644 --- a/web/lang/pl_pl.php +++ b/web/lang/pl_pl.php @@ -584,6 +584,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Poprzedni', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/pt_br.php b/web/lang/pt_br.php index c7c3caf42..229753cbf 100644 --- a/web/lang/pt_br.php +++ b/web/lang/pt_br.php @@ -509,6 +509,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Ant.', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/ro_ro.php b/web/lang/ro_ro.php index a36c4de6c..aaec7f62e 100644 --- a/web/lang/ro_ro.php +++ b/web/lang/ro_ro.php @@ -540,6 +540,18 @@ $SLANG = array( 'Preset' => 'Presetare', 'Presets' => 'Presetări', 'Prev' => 'Prev', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/ru_ru.php b/web/lang/ru_ru.php index 8d0d24a7d..7f8237198 100644 --- a/web/lang/ru_ru.php +++ b/web/lang/ru_ru.php @@ -573,6 +573,18 @@ $SLANG = array( 'Preset' => 'Предустановка', 'Presets' => 'Предустановки', 'Prev' => 'Пред.', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Поиск', // Added - 2009-03-31 'ProfileProbe' => 'Поиск потока', // Added - 2015-04-18 'ProfileProbeIntro' => 'В этом списке показаны существующие профили потока выбранной камеры.

Выберите нужный из списка ниже.

Обратите внимание, что ZoneMinder не может добавить дополнительный профиль, и что выбор профиля может переписать настройки определенные для этого монитора.

', // Added - 2015-04-18 diff --git a/web/lang/se_se.php b/web/lang/se_se.php index e624e5696..97101ff62 100644 --- a/web/lang/se_se.php +++ b/web/lang/se_se.php @@ -570,6 +570,18 @@ $SLANG = array( 'Preset' => 'Förinställning', 'Presets' => 'Förinställningar', 'Prev' => 'Föreg.', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/skins/classic/css/base/views/privacy.css b/web/skins/classic/css/base/views/privacy.css new file mode 100644 index 000000000..f368fa110 --- /dev/null +++ b/web/skins/classic/css/base/views/privacy.css @@ -0,0 +1,14 @@ +h6 { + text-align: left; + font-weight: bold; + text-decoration: underline; +} + +p { + text-align: left; +} + +ul { + text-align: left; + list-style-type: disc; +} diff --git a/web/skins/classic/views/js/privacy.js b/web/skins/classic/views/js/privacy.js new file mode 100644 index 000000000..4b3499981 --- /dev/null +++ b/web/skins/classic/views/js/privacy.js @@ -0,0 +1,9 @@ +function submitForm( element ) { + var form = element.form; + if ( form.option.selectedIndex == 0 ) + form.view.value = currentView; + else + form.view.value = 'none'; + form.submit(); +} + diff --git a/web/skins/classic/views/privacy.php b/web/skins/classic/views/privacy.php new file mode 100644 index 000000000..1480c2973 --- /dev/null +++ b/web/skins/classic/views/privacy.php @@ -0,0 +1,74 @@ + translate('Accept'), + "decline" => translate('Decline'), +); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, translate('Privacy') ); +?> + +
+ +
+
+ + +
+

+
+ +
+

+
+ +
+

+
+ +
+

+
+ +

+

+

+

+ +
+ +
+
+
+
+ + From 15a6eb7e784ed126256044f125cb6e6ca4962d2e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Aug 2018 15:33:43 -0400 Subject: [PATCH 20/52] Revert "Add Privacy Statement (#2176)" (#2179) This reverts commit 56f4d768c2783081e5918f9c5128a1b630d67c2c. --- .../lib/ZoneMinder/ConfigData.pm.in | 9 --- scripts/zmupdate.pl.in | 5 -- web/includes/actions.php | 25 +------ web/index.php | 5 -- web/lang/big5_big5.php | 12 --- web/lang/cn_zh.php | 12 --- web/lang/cs_cz.php | 12 --- web/lang/de_de.php | 12 --- web/lang/dk_dk.php | 12 --- web/lang/en_gb.php | 16 +--- web/lang/es_ar.php | 12 --- web/lang/es_es.php | 12 --- web/lang/et_ee.php | 12 --- web/lang/fr_fr.php | 12 --- web/lang/he_il.php | 12 --- web/lang/hu_hu.php | 12 --- web/lang/it_it.php | 12 --- web/lang/ja_jp.php | 12 --- web/lang/nl_nl.php | 12 --- web/lang/pl_pl.php | 12 --- web/lang/pt_br.php | 12 --- web/lang/ro_ro.php | 12 --- web/lang/ru_ru.php | 12 --- web/lang/se_se.php | 12 --- web/skins/classic/css/base/views/privacy.css | 14 ---- web/skins/classic/views/js/privacy.js | 9 --- web/skins/classic/views/privacy.php | 74 ------------------- 27 files changed, 3 insertions(+), 382 deletions(-) delete mode 100644 web/skins/classic/css/base/views/privacy.css delete mode 100644 web/skins/classic/views/js/privacy.js delete mode 100644 web/skins/classic/views/privacy.php diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 6a3a66dae..c6136717a 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -3882,15 +3882,6 @@ our @options = ( readonly => 1, category => 'dynamic', }, - { - name => 'ZM_SHOW_PRIVACY', - default => 'yes', - description => 'Present the privacy statment', - help => '', - type => $types{boolean}, - readonly => 1, - category => 'dynamic', - }, { name => 'ZM_SSMTP_MAIL', default => 'no', diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index 45d45851a..f428ea1f9 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -922,11 +922,6 @@ if ( $version ) { zmDbDisconnect(); die( "Can't find upgrade from version '$version'" ); } - # Re-enable the privacy popup after each upgrade - my $sql = "update Config set Value = 1 where Name = 'ZM_SHOW_PRIVACY'"; - my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() ); - $sth->finish(); print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" ); } zmDbDisconnect(); diff --git a/web/includes/actions.php b/web/includes/actions.php index 2f5df5823..a38515f3d 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -547,7 +547,7 @@ if ( canEdit( 'Monitors' ) ) { $maxSeq = dbFetchOne('SELECT MAX(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence'); $changes[] = 'Sequence = '.($maxSeq+1); - if ( dbQuery/usr/share/zoneminder/www/lang/en_gb.php( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ) ) { + if ( dbQuery( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ) ) { $mid = dbInsertId(); $zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height']; dbQuery( "insert into Zones set MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) ); @@ -863,29 +863,6 @@ if ( canEdit( 'System' ) ) { } } // end switch option } - if ( $action == 'privacy' && isset($_REQUEST['option'] ) ) { - $option = $_REQUEST['option']; - switch( $option ) { - case 'decline' : - { - dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); - dbQuery( "update Config set Value = '0' where Name = 'ZM_TELEMETRY_DATA'" ); - $view = 'console'; - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; - break; - } - case 'accept' : - { - dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); - dbQuery( "update Config set Value = '1' where Name = 'ZM_TELEMETRY_DATA'" ); - $view = 'console'; - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; - break; - } - default: # Enable the privacy statement if we somehow submit something other than accept or decline - dbQuery( "update Config set Value = '1' where Name = 'ZM_SHOW_PRIVACY'" ); - } // end switch option - } if ( $action == 'options' && isset($_REQUEST['tab']) ) { $configCat = $configCats[$_REQUEST['tab']]; $changed = false; diff --git a/web/index.php b/web/index.php index 69745ce3c..7f823f1fd 100644 --- a/web/index.php +++ b/web/index.php @@ -221,11 +221,6 @@ if ( ZM_OPT_USE_AUTH and ! isset($user) ) { $request = null; } -if ( ZM_SHOW_PRIVACY && canEdit('System') ) { - Logger::Debug("Redirecting to privacy" ); - $view = 'privacy'; - $request = null; -} if ( $redirect ) { header('Location: '.$redirect); diff --git a/web/lang/big5_big5.php b/web/lang/big5_big5.php index b2e21264b..b8bc173a5 100644 --- a/web/lang/big5_big5.php +++ b/web/lang/big5_big5.php @@ -573,18 +573,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => '上一事件', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/cn_zh.php b/web/lang/cn_zh.php index 39206d038..9ed821417 100644 --- a/web/lang/cn_zh.php +++ b/web/lang/cn_zh.php @@ -569,18 +569,6 @@ $SLANG = array( 'Preset' => '预置', 'Presets' => '预置', 'Prev' => '前', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/cs_cz.php b/web/lang/cs_cz.php index 228c2618d..adcdeb61d 100644 --- a/web/lang/cs_cz.php +++ b/web/lang/cs_cz.php @@ -569,18 +569,6 @@ $SLANG = array( 'Preset' => 'Předvolba', 'Presets' => 'Předvolby', 'Prev' => 'Zpět', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/de_de.php b/web/lang/de_de.php index 18a4e9cfe..424d91e94 100644 --- a/web/lang/de_de.php +++ b/web/lang/de_de.php @@ -572,18 +572,6 @@ $SLANG = array( 'Presets' => 'Voreinstellungen', 'Prev' => 'Vorheriges', 'Probe' => 'Suchen', // Added - 2009-03-31 - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'ProfileProbe' => 'Streamsonde', // Added - 2015-04-18 'ProfileProbeIntro' => 'Die folgende Liste zeigt die verfügbaren Streamingprofile der ausgewählten Kamera.

Wähle den gewünschten Eintrag aus der folgenden Liste.

Bitte Beachten: Zoneminder kann keine zusätzlichen Profile konfigurieren. Die Auswahl einer Kamera kann bereits eingetragene Werte im aktuellen Monitor überschreiben.

', // Added - 2015-04-18 'Progress' => 'Fortschritt', // Added - 2015-04-18 diff --git a/web/lang/dk_dk.php b/web/lang/dk_dk.php index b0c066237..605f9fb19 100644 --- a/web/lang/dk_dk.php +++ b/web/lang/dk_dk.php @@ -580,18 +580,6 @@ $SLANG = array( 'Preset' => 'Forudindstilling', 'Presets' => 'Forudindstillinger', 'Prev' => 'Forrige', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', 'ProfileProbe' => 'Stream Probe', 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index bb4fe9b26..ba77b156e 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -600,18 +600,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Prev', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', 'ProfileProbe' => 'Stream Probe', 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', @@ -666,7 +654,7 @@ $SLANG = array( 'Select' => 'Select', 'SelectFormat' => 'Select Format', 'SelectLog' => 'Select Log', - 'SelfIntersecting' => 'P/usr/share/zoneminder/www/lang/en_gb.phpolygon edges must not intersect', + 'SelfIntersecting' => 'Polygon edges must not intersect', 'SetNewBandwidth' => 'Set New Bandwidth', 'SetPreset' => 'Set Preset', 'Set' => 'Set', @@ -674,7 +662,7 @@ $SLANG = array( 'ShowFilterWindow' => 'Show Filter Window', 'ShowTimeline' => 'Show Timeline', 'SignalCheckColour' => 'Signal Check Colour', - 'SignalCheckPoints' => 'S/usr/share/zoneminder/www/lang/en_gb.phpignal Check Points', + 'SignalCheckPoints' => 'Signal Check Points', 'Size' => 'Size', 'SkinDescription' => 'Change the skin for this session', 'CSSDescription' => 'Change the css for this session', diff --git a/web/lang/es_ar.php b/web/lang/es_ar.php index 0cb51c27b..cbb3c2d88 100644 --- a/web/lang/es_ar.php +++ b/web/lang/es_ar.php @@ -520,18 +520,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Prev', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/es_es.php b/web/lang/es_es.php index 0397b9ea0..3e27d0fae 100644 --- a/web/lang/es_es.php +++ b/web/lang/es_es.php @@ -569,18 +569,6 @@ $SLANG = array( 'Preset' => 'Programa', 'Presets' => 'Programas', 'Prev' => 'Anterior', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Sondear', 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/et_ee.php b/web/lang/et_ee.php index 92360a20b..250728550 100644 --- a/web/lang/et_ee.php +++ b/web/lang/et_ee.php @@ -576,18 +576,6 @@ $SLANG = array( 'Preset' => 'Eelseatud', 'Presets' => 'Eelseaded', 'Prev' => 'Prev', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/fr_fr.php b/web/lang/fr_fr.php index 227adf0e9..b140886fe 100644 --- a/web/lang/fr_fr.php +++ b/web/lang/fr_fr.php @@ -575,18 +575,6 @@ $SLANG = array( 'Preset' => 'Préréglage', 'Presets' => 'Préréglages', 'Prev' => 'Précédent', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Autodétection', // Added - 2009-03-31 'ProfileProbe' => 'Détection de flux', // Added - 2015-04-18 'ProfileProbeIntro' => 'La liste ci-dessous montre les profils de flux existants pour la caméra sélectionnée.

Sélectionnez le profil désiré dans la liste ci-dessous.

Veuillez noter que ZoneMinder ne peut pas configurer de profils additionels et que la sauvegarde entraînera l\'écrasement des paramètres déjà configurés pour la caméra en cours.

', // Added - 2015-04-18 diff --git a/web/lang/he_il.php b/web/lang/he_il.php index 958b8e57f..f8c8897a4 100644 --- a/web/lang/he_il.php +++ b/web/lang/he_il.php @@ -569,18 +569,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'ä÷åãí', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/hu_hu.php b/web/lang/hu_hu.php index fe347fae7..3f0928be1 100644 --- a/web/lang/hu_hu.php +++ b/web/lang/hu_hu.php @@ -612,18 +612,6 @@ $SLANG = array( 'Preset' => 'Előre beállított profil', 'Presets' => 'Előre beállított profilok', 'Prev' => 'Előző', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Érzékelés', 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/it_it.php b/web/lang/it_it.php index fe2e24bb7..338f2c07f 100644 --- a/web/lang/it_it.php +++ b/web/lang/it_it.php @@ -574,18 +574,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Prec', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Prova la telecamera', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/ja_jp.php b/web/lang/ja_jp.php index 33d797725..340d2caac 100644 --- a/web/lang/ja_jp.php +++ b/web/lang/ja_jp.php @@ -570,18 +570,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => '前', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/nl_nl.php b/web/lang/nl_nl.php index 87ab57c70..fca70a829 100644 --- a/web/lang/nl_nl.php +++ b/web/lang/nl_nl.php @@ -570,18 +570,6 @@ $SLANG = array( 'Preset' => 'Voorkeur', 'Presets' => 'Voorkeuren', 'Prev' => 'Vorige', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Scan', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/pl_pl.php b/web/lang/pl_pl.php index 1b4883db7..325c2e1b9 100644 --- a/web/lang/pl_pl.php +++ b/web/lang/pl_pl.php @@ -584,18 +584,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Poprzedni', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/pt_br.php b/web/lang/pt_br.php index 229753cbf..c7c3caf42 100644 --- a/web/lang/pt_br.php +++ b/web/lang/pt_br.php @@ -509,18 +509,6 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Ant.', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/ro_ro.php b/web/lang/ro_ro.php index aaec7f62e..a36c4de6c 100644 --- a/web/lang/ro_ro.php +++ b/web/lang/ro_ro.php @@ -540,18 +540,6 @@ $SLANG = array( 'Preset' => 'Presetare', 'Presets' => 'Presetări', 'Prev' => 'Prev', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/lang/ru_ru.php b/web/lang/ru_ru.php index 7f8237198..8d0d24a7d 100644 --- a/web/lang/ru_ru.php +++ b/web/lang/ru_ru.php @@ -573,18 +573,6 @@ $SLANG = array( 'Preset' => 'Предустановка', 'Presets' => 'Предустановки', 'Prev' => 'Пред.', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Поиск', // Added - 2009-03-31 'ProfileProbe' => 'Поиск потока', // Added - 2015-04-18 'ProfileProbeIntro' => 'В этом списке показаны существующие профили потока выбранной камеры.

Выберите нужный из списка ниже.

Обратите внимание, что ZoneMinder не может добавить дополнительный профиль, и что выбор профиля может переписать настройки определенные для этого монитора.

', // Added - 2015-04-18 diff --git a/web/lang/se_se.php b/web/lang/se_se.php index 97101ff62..e624e5696 100644 --- a/web/lang/se_se.php +++ b/web/lang/se_se.php @@ -570,18 +570,6 @@ $SLANG = array( 'Preset' => 'Förinställning', 'Presets' => 'Förinställningar', 'Prev' => 'Föreg.', - 'Privacy' => 'Privacy', - 'PrivacyAbout' => 'About', - 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', - 'PrivacyContact' => 'Contact', - 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', - 'PrivacyCookies' => 'Cookies', - 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', - 'PrivacyTelemetry' => 'Telemetry', - 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are our there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', - 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', - 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', - 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', // Added - 2009-03-31 'ProfileProbe' => 'Stream Probe', // Added - 2015-04-18 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', // Added - 2015-04-18 diff --git a/web/skins/classic/css/base/views/privacy.css b/web/skins/classic/css/base/views/privacy.css deleted file mode 100644 index f368fa110..000000000 --- a/web/skins/classic/css/base/views/privacy.css +++ /dev/null @@ -1,14 +0,0 @@ -h6 { - text-align: left; - font-weight: bold; - text-decoration: underline; -} - -p { - text-align: left; -} - -ul { - text-align: left; - list-style-type: disc; -} diff --git a/web/skins/classic/views/js/privacy.js b/web/skins/classic/views/js/privacy.js deleted file mode 100644 index 4b3499981..000000000 --- a/web/skins/classic/views/js/privacy.js +++ /dev/null @@ -1,9 +0,0 @@ -function submitForm( element ) { - var form = element.form; - if ( form.option.selectedIndex == 0 ) - form.view.value = currentView; - else - form.view.value = 'none'; - form.submit(); -} - diff --git a/web/skins/classic/views/privacy.php b/web/skins/classic/views/privacy.php deleted file mode 100644 index 1480c2973..000000000 --- a/web/skins/classic/views/privacy.php +++ /dev/null @@ -1,74 +0,0 @@ - translate('Accept'), - "decline" => translate('Decline'), -); - -$focusWindow = true; - -xhtmlHeaders(__FILE__, translate('Privacy') ); -?> - -
- -
-
- - -
-

-
- -
-

-
- -
-

-
- -
-

-
- -

-

-

-

- -
- -
-
-
-
- - From bb70c9f14e3a7a62261678a52614eca8d51967c9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Aug 2018 08:28:44 -0400 Subject: [PATCH 21/52] Cleanup Licenses. Fixes #1276 --- .../lib/ZoneMinder/Control/Trendnet.pm | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm index a30aaaf46..1fddf2c01 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm @@ -1,8 +1,7 @@ #=========================================================================== # -# ZoneMinder Trendnet IP Control Protocol Module, $Date: $, $Revision: $ -# Copyright (C) 2018 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC -# +# ZoneMinder Trendnet IP Control Protocol Module +# Copyright (C) 2018 ZoneMinder ZoneMinder LLC # # ========================================================================== # @@ -422,7 +421,6 @@ sub reset { 1; __END__ -# Below is stub documentation for your module. You'd better edit it! =head1 NAME @@ -435,19 +433,6 @@ ZoneMinder::Control::Trendnet - Perl module for Trendnet cameras =head1 DESCRIPTION -Stub documentation for Trendnet PTZ Sctrol - -=head2 EXPORT - -None by default. - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2018 by ZoneMinder LLC - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.3 or, -at your option, any later version of Perl 5 you may have available. - +Module for accessing the PTZ functions of Trendnet PTZ IP Cameras =cut From 40cd27e68ac4473f8de447e42ee7c4dcf499f607 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Aug 2018 17:21:54 -0400 Subject: [PATCH 22/52] when refreshing because ajax failed, reload the current view, not just index.php --- web/skins/classic/js/skin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index 78abe3a75..9e82a9c8a 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -199,7 +199,7 @@ if ( currentView != 'none' && currentView != 'login' ) { console.log( "Request Failed: " + err ); // The idea is that this should only fail due to auth, so reload the page // which should go to login if it can't stay logged in. - window.location.href = thisUrl; + window.location.href = thisUrl+'?view='+currentView; }); } From 1fa78c5aa8737ecd3fa4794c5f245195f710b1c5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 17 Aug 2018 08:14:13 -0400 Subject: [PATCH 23/52] Fix up licensing and copyright --- .../lib/ZoneMinder/Control/Trendnet.pm | 92 +++++++------------ 1 file changed, 35 insertions(+), 57 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm index a30aaaf46..30534c516 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm @@ -1,42 +1,3 @@ -#=========================================================================== -# -# ZoneMinder Trendnet IP Control Protocol Module, $Date: $, $Revision: $ -# Copyright (C) 2018 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC8 ZoneMinder LLC -# -# -# ========================================================================== -# -# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# ========================================================================== -# -# This module contains the implementation of the Trendnet # IP camera control -# protocol. Has been tested with TV-IP862IC -# -# Under control capability: -# -# * Main: Can wake, can sleep, can reset -# * Move: Can move, can move diagonally, can move mapped, can move relative -# * Pan: Can pan -# * Tilt: Can tilt -# * Presets: Has presets, num presets 20, has home preset (don't set presets via camera's web server, only set via ZM.) -# -# Under control tab in the monitor itself: -# -# Controllable -# Control type is the name you gave it in control capability above -# Control address is the camera's ip address AND web port. example: 192.168.1.1:80 -# You can also put the authentication information here and change the -# protocol to https using something like https://admin:password@192.168.1.1:80 -# - package ZoneMinder::Control::Trendnet; use 5.006; @@ -48,27 +9,19 @@ require ZoneMinder::Control; our @ISA = qw(ZoneMinder::Control); -# -# ******** YOU MUST CHANGE THE FOLLOWING LINES TO MATCH YOUR CAMERA! ********** -# # You do not need to change the REALM, but you can get slightly faster response # by setting so that the first auth request succeeds. # -# The username and password should be passed in the ControlDevice field but you +# The username and password should be passed in the ControlAddress field but you # can set them here if you want. # + our $REALM = ''; our $PROTOCOL = 'http://'; our $USERNAME = 'admin'; our $PASSWORD = ''; our $ADDRESS = ''; -# ========================================================================== -# -# Trendnet TV-IP672PI Control Protocol -# -# ========================================================================== - use ZoneMinder::Logger qw(:all); use ZoneMinder::Config qw(:all); @@ -422,7 +375,6 @@ sub reset { 1; __END__ -# Below is stub documentation for your module. You'd better edit it! =head1 NAME @@ -430,12 +382,29 @@ ZoneMinder::Control::Trendnet - Perl module for Trendnet cameras =head1 SYNOPSIS - use ZoneMinder::Database; - place this in /usr/share/perl5/ZoneMinder/Control +use ZoneMinder::Control::Trendnet; +place this in /usr/share/perl5/ZoneMinder/Control =head1 DESCRIPTION -Stub documentation for Trendnet PTZ Sctrol +This module contains the implementation of the Trendnet # IP camera control +protocol. Has been tested with TV-IP862IC + +Under control capability: + +* Main: Can wake, can sleep, can reset +* Move: Can move, can move diagonally, can move mapped, can move relative +* Pan: Can pan +* Tilt: Can tilt +* Presets: Has presets, num presets 20, has home preset (don't set presets via camera's web server, only set via ZM.) + +Under control tab in the monitor itself: + +Controllable +Control type is the name you gave it in control capability above +Control address is the camera's ip address AND web port. example: 192.168.1.1:80 +You can also put the authentication information here and change the +protocol to https using something like https://admin:password@192.168.1.1:80 =head2 EXPORT @@ -443,11 +412,20 @@ None by default. =head1 COPYRIGHT AND LICENSE -Copyright (C) 2018 by ZoneMinder LLC +Copyright (C) 2018 ZoneMinder LLC -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.3 or, -at your option, any later version of Perl 5 you may have available. +This library 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 library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. =cut From 24f8d63b6992f114c21697eeebaf615656a6db5a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 20 Aug 2018 11:13:38 -0400 Subject: [PATCH 24/52] comment out a debug line --- web/ajax/log.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index b5a95899b..375b53a05 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -95,7 +95,7 @@ switch ( $_REQUEST['task'] ) { foreach ( dbFetchAll($sql, NULL, $values) as $log ) { $log['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($log['TimeKey'])); - Warning("TimeKey: " . $log['TimeKey'] . 'Intval:'.intval($log['TimeKey']).' DateTime:'.$log['DateTime']); + #Warning("TimeKey: " . $log['TimeKey'] . 'Intval:'.intval($log['TimeKey']).' DateTime:'.$log['DateTime']); #$log['DateTime'] = preg_replace('/^\d+/', strftime('%Y-%m-%d %H:%M:%S', intval($log['TimeKey'])), $log['TimeKey']); $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; $log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message']); From 4e30a9e71c6090c3efa38b9d2b13467b5b5ebbda Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 21 Aug 2018 12:50:33 -0400 Subject: [PATCH 25/52] Stats.EventId must be a bigint too --- db/zm_create.sql.in | 2 +- db/zm_update-1.31.46.sql | 2 ++ version | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 db/zm_update-1.31.46.sql diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 2bd0706ef..f39c9a90b 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -581,7 +581,7 @@ DROP TABLE IF EXISTS `Stats`; CREATE TABLE `Stats` ( `MonitorId` int(10) unsigned NOT NULL default '0', `ZoneId` int(10) unsigned NOT NULL default '0', - `EventId` int(10) unsigned NOT NULL default '0', + `EventId` BIGINT UNSIGNED NOT NULL, `FrameId` int(10) unsigned NOT NULL default '0', `PixelDiff` tinyint(3) unsigned NOT NULL default '0', `AlarmPixels` int(10) unsigned NOT NULL default '0', diff --git a/db/zm_update-1.31.46.sql b/db/zm_update-1.31.46.sql new file mode 100644 index 000000000..8c9767e75 --- /dev/null +++ b/db/zm_update-1.31.46.sql @@ -0,0 +1,2 @@ +ALTER TABLE Stats MODIFY COLUMN EventId bigint unsigned NOT NULL; + diff --git a/version b/version index 6701dcb1c..2bb17d951 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.45 +1.31.46 From 90eda0b88b793da4b3ebdfced08dfcdaa6b1639d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 22 Aug 2018 11:14:00 -0400 Subject: [PATCH 26/52] spacing, remove extra parenthesis --- src/zm_zone.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index b62ad41fe..401366b2d 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -236,7 +236,9 @@ bool Zone::CheckAlarms(const Image *delta_image) { if ( pixel_diff_count && alarm_pixels ) pixel_diff = pixel_diff_count/alarm_pixels; - Debug(5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff); + + Debug(5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", + alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff); if ( alarm_pixels ) { if ( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) { @@ -312,7 +314,8 @@ bool Zone::CheckAlarms(const Image *delta_image) { if ( config.record_diag_images ) diff_image->WriteJpeg(diag_path); - Debug(5, "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels); + Debug(5, "Got %d filtered pixels, need %d -> %d", + alarm_filter_pixels, min_filter_pixels, max_filter_pixels); if ( alarm_filter_pixels ) { if ( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) { @@ -328,7 +331,7 @@ bool Zone::CheckAlarms(const Image *delta_image) { return false; } - score = (100*alarm_filter_pixels)/(polygon.Area()); + score = (100*alarm_filter_pixels)/polygon.Area(); if ( score < 1 ) score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ Debug(5, "Current score is %d", score); @@ -438,7 +441,8 @@ bool Zone::CheckAlarms(const Image *delta_image) { alarm_blobs--; - Debug(6, "Merging blob %d with %d at %d,%d, %d current blobs", bss->tag, bsm->tag, x, y, alarm_blobs); + Debug(6, "Merging blob %d with %d at %d,%d, %d current blobs", + bss->tag, bsm->tag, x, y, alarm_blobs); // Clear out the old blob bss->tag = 0; @@ -476,7 +480,11 @@ bool Zone::CheckAlarms(const Image *delta_image) { BlobStats *bs = &blob_stats[i]; // See if we can recycle one first, only if it's at least two rows up if ( bs->count && bs->hi_y < (int)(y-1) ) { - if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) { + if ( + (min_blob_pixels && bs->count < min_blob_pixels) + || + (max_blob_pixels && bs->count > max_blob_pixels) + ) { if ( config.create_analysis_images || config.record_diag_images ) { for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) { spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); From d97eea886a8de84c337387d52415f9e832352934 Mon Sep 17 00:00:00 2001 From: vajonam Date: Wed, 22 Aug 2018 12:58:26 -0400 Subject: [PATCH 27/52] fix scoring algorithim, to use max_alarm_size when specified instead of the size of the zone. (#2186) --- src/zm_zone.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index b62ad41fe..ce5ce91c2 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -252,7 +252,11 @@ bool Zone::CheckAlarms(const Image *delta_image) { return false; } - score = (100*alarm_pixels)/polygon.Area(); + if (max_alarm_pixels != 0) + score = (100*alarm_pixels)/max_alarm_pixels; + else + score = (100*alarm_pixels)/polygon.Area(); + if ( score < 1 ) score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ Debug(5, "Current score is %d", score); @@ -328,7 +332,11 @@ bool Zone::CheckAlarms(const Image *delta_image) { return false; } - score = (100*alarm_filter_pixels)/(polygon.Area()); + if (max_filter_pixels != 0) + score = (100*alarm_filter_pixels)/(max_filter_pixels); + else + score = (100*alarm_filter_pixels)/polygon.Area(); + if ( score < 1 ) score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ Debug(5, "Current score is %d", score); @@ -589,8 +597,12 @@ bool Zone::CheckAlarms(const Image *delta_image) { /* No blobs */ return false; } - - score = (100*alarm_blob_pixels)/(polygon.Area()); + + if (max_blob_pixels != 0) + score = (100*alarm_blob_pixels)/(max_blob_pixels); + else + score = (100*alarm_blob_pixels)/polygon.Area(); + if ( score < 1 ) score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ Debug(5, "Current score is %d", score); From 627d47980ae25d9f1a5285f90bdac9fd8e8592ca Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 22 Aug 2018 16:33:11 -0400 Subject: [PATCH 28/52] prevent killall zombies by ignoring SIGCHLD at startup --- scripts/zmdc.pl.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in index 6e6663b18..e26247894 100644 --- a/scripts/zmdc.pl.in +++ b/scripts/zmdc.pl.in @@ -272,6 +272,8 @@ sub run { ."\n" ); + # We don't want to leave killall zombies, so ignore SIGCHLD + $SIG{CHLD} = 'IGNORE'; # Tell any existing processes to die, wait 1 second between TERM and KILL killAll(1); From 21d193294f37d25c041d3b91bd3113cc28e1a934 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 22 Aug 2018 17:22:40 -0400 Subject: [PATCH 29/52] Log errors shouldn't be fatal --- web/includes/logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/logger.php b/web/includes/logger.php index 0d7334ac7..8bc81fb97 100644 --- a/web/includes/logger.php +++ b/web/includes/logger.php @@ -406,7 +406,7 @@ class Logger { $result = $stmt->execute( array( sprintf( '%d.%06d', $time['sec'], $time['usec'] ), $this->id, getmypid(), $level, $code, $string, $file, $line ) ); } catch(PDOException $ex) { $this->databaseLevel = self::NOLOG; - Fatal( "Can't write log entry '$sql': ". $ex->getMessage() ); + Error("Can't write log entry '$sql': ". $ex->getMessage()); } } // This has to be last as trigger_error can be fatal From d64dc4f288712c6b4e1363033c98f98ee15ffbe5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 24 Aug 2018 10:49:30 -0400 Subject: [PATCH 30/52] Frames EventId somehow never got an update even though zm_create.sql did.So add an update to convert EventId to a bigint. --- db/zm_update-1.31.47.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 db/zm_update-1.31.47.sql diff --git a/db/zm_update-1.31.47.sql b/db/zm_update-1.31.47.sql new file mode 100644 index 000000000..155fb29cc --- /dev/null +++ b/db/zm_update-1.31.47.sql @@ -0,0 +1,2 @@ +ALTER TABLE Frames MODIFY COLUMN EventId bigint unsigned NOT NULL; + From c271948f3d8f139b1b0ad418e22e0192b18e6cbd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 24 Aug 2018 12:26:44 -0400 Subject: [PATCH 31/52] bump version to 1.31.47 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 2bb17d951..d56f906c5 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.46 +1.31.47 From 718bb6bba30928ba6275fcfb66a74b0fb2a69e4f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 28 Aug 2018 10:37:02 -0400 Subject: [PATCH 32/52] Remove zm from alter statement --- db/zm_update-1.31.43.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/zm_update-1.31.43.sql b/db/zm_update-1.31.43.sql index 05a92288e..c97405903 100644 --- a/db/zm_update-1.31.43.sql +++ b/db/zm_update-1.31.43.sql @@ -5,7 +5,7 @@ -- Add Refresh column to Monitors table -- -ALTER TABLE `zm`.`Monitors` +ALTER TABLE `Monitors` CHANGE COLUMN `Type` `Type` ENUM('Local', 'Remote', 'File', 'Ffmpeg', 'Libvlc', 'cURL', 'WebSite') NOT NULL DEFAULT 'Local' ; SET @s = (SELECT IF( From 8f0fb0843a90cd7c9b8091daa012bec62f92551e Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 30 Aug 2018 12:25:02 -0500 Subject: [PATCH 33/52] Add Privacy Statement (#2194) * initial implementation of privacy popup * split the privacy text and run it through translate * change style of toggle button, validate the form * fix copy/paste error * fix typos * display privacy view inline rather than popup * display privacy inline if show_privacy flag set * redirect to console after selection is made * typo * css formatting * update privacy verbiage * create and load default.php * fix typos * fix erroneous copy/paste --- .../lib/ZoneMinder/ConfigData.pm.in | 9 +++ scripts/zmupdate.pl.in | 5 ++ web/includes/actions.php | 23 ++++++ web/includes/lang.php | 8 +- web/index.php | 5 ++ web/lang/default.php | 44 +++++++++++ web/lang/en_gb.php | 12 +++ web/skins/classic/css/base/views/privacy.css | 14 ++++ web/skins/classic/views/js/privacy.js | 9 +++ web/skins/classic/views/privacy.php | 74 +++++++++++++++++++ 10 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 web/lang/default.php create mode 100644 web/skins/classic/css/base/views/privacy.css create mode 100644 web/skins/classic/views/js/privacy.js create mode 100644 web/skins/classic/views/privacy.php diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index c6136717a..6a3a66dae 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -3882,6 +3882,15 @@ our @options = ( readonly => 1, category => 'dynamic', }, + { + name => 'ZM_SHOW_PRIVACY', + default => 'yes', + description => 'Present the privacy statment', + help => '', + type => $types{boolean}, + readonly => 1, + category => 'dynamic', + }, { name => 'ZM_SSMTP_MAIL', default => 'no', diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index f428ea1f9..45d45851a 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -922,6 +922,11 @@ if ( $version ) { zmDbDisconnect(); die( "Can't find upgrade from version '$version'" ); } + # Re-enable the privacy popup after each upgrade + my $sql = "update Config set Value = 1 where Name = 'ZM_SHOW_PRIVACY'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( ) or die( "Can't execute: ".$sth->errstr() ); + $sth->finish(); print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" ); } zmDbDisconnect(); diff --git a/web/includes/actions.php b/web/includes/actions.php index a38515f3d..cd67fc81c 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -863,6 +863,29 @@ if ( canEdit( 'System' ) ) { } } // end switch option } + if ( $action == 'privacy' && isset($_REQUEST['option'] ) ) { + $option = $_REQUEST['option']; + switch( $option ) { + case 'decline' : + { + dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); + dbQuery( "update Config set Value = '0' where Name = 'ZM_TELEMETRY_DATA'" ); + $view = 'console'; + $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; + break; + } + case 'accept' : + { + dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); + dbQuery( "update Config set Value = '1' where Name = 'ZM_TELEMETRY_DATA'" ); + $view = 'console'; + $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; + break; + } + default: # Enable the privacy statement if we somehow submit something other than accept or decline + dbQuery( "update Config set Value = '1' where Name = 'ZM_SHOW_PRIVACY'" ); + } // end switch option + } if ( $action == 'options' && isset($_REQUEST['tab']) ) { $configCat = $configCats[$_REQUEST['tab']]; $changed = false; diff --git a/web/includes/lang.php b/web/includes/lang.php index 0cab566b7..0c40e7f60 100644 --- a/web/includes/lang.php +++ b/web/includes/lang.php @@ -49,8 +49,14 @@ function loadLanguage( $prefix="" ) return( false ); } -if ( $langFile = loadLanguage() ) +if ( $langFile = loadLanguage() ) { require_once( $langFile ); + require_once( 'lang/default.php' ); + foreach ($DLANG as $key => $value) { + if ( ! array_key_exists( $key, $SLANG ) ) + $SLANG[$key] = $DLANG[$key]; + } +} // diff --git a/web/index.php b/web/index.php index 7f823f1fd..69745ce3c 100644 --- a/web/index.php +++ b/web/index.php @@ -221,6 +221,11 @@ if ( ZM_OPT_USE_AUTH and ! isset($user) ) { $request = null; } +if ( ZM_SHOW_PRIVACY && canEdit('System') ) { + Logger::Debug("Redirecting to privacy" ); + $view = 'privacy'; + $request = null; +} if ( $redirect ) { header('Location: '.$redirect); diff --git a/web/lang/default.php b/web/lang/default.php new file mode 100644 index 000000000..85f27cfe1 --- /dev/null +++ b/web/lang/default.php @@ -0,0 +1,44 @@ + 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are out there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', +); + +?> + diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index ba77b156e..27357ade9 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -600,6 +600,18 @@ $SLANG = array( 'Preset' => 'Preset', 'Presets' => 'Presets', 'Prev' => 'Prev', + 'Privacy' => 'Privacy', + 'PrivacyAbout' => 'About', + 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.', + 'PrivacyContact' => 'Contact', + 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.

For support, there are three primary ways to engage with the community:

Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.

', + 'PrivacyCookies' => 'Cookies', + 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.', + 'PrivacyTelemetry' => 'Telemetry', + 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are out there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.', + 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
  • A unique identifier (UUID)
  • City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
  • Current time
  • Total number of monitors
  • Total number of events
  • System architecture
  • Operating system kernel, distro, and distro version
  • Version of ZoneMinder
  • Total amount of memory
  • Number of cpu cores
', + 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
  • Id
  • Name
  • Type
  • Function
  • Width
  • Height
  • Colours
  • MaxFPS
  • AlarmMaxFPS
', + 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don’t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.', 'Probe' => 'Probe', 'ProfileProbe' => 'Stream Probe', 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .

Select the desired entry from the list below.

Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.

', diff --git a/web/skins/classic/css/base/views/privacy.css b/web/skins/classic/css/base/views/privacy.css new file mode 100644 index 000000000..f368fa110 --- /dev/null +++ b/web/skins/classic/css/base/views/privacy.css @@ -0,0 +1,14 @@ +h6 { + text-align: left; + font-weight: bold; + text-decoration: underline; +} + +p { + text-align: left; +} + +ul { + text-align: left; + list-style-type: disc; +} diff --git a/web/skins/classic/views/js/privacy.js b/web/skins/classic/views/js/privacy.js new file mode 100644 index 000000000..4b3499981 --- /dev/null +++ b/web/skins/classic/views/js/privacy.js @@ -0,0 +1,9 @@ +function submitForm( element ) { + var form = element.form; + if ( form.option.selectedIndex == 0 ) + form.view.value = currentView; + else + form.view.value = 'none'; + form.submit(); +} + diff --git a/web/skins/classic/views/privacy.php b/web/skins/classic/views/privacy.php new file mode 100644 index 000000000..1480c2973 --- /dev/null +++ b/web/skins/classic/views/privacy.php @@ -0,0 +1,74 @@ + translate('Accept'), + "decline" => translate('Decline'), +); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, translate('Privacy') ); +?> + +
+ +
+
+ + +
+

+
+ +
+

+
+ +
+

+
+ +
+

+
+ +

+

+

+

+ +
+ +
+
+
+
+ + From 18c88be5504e78f5ad0dce2262f01fcf52d923cc Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 31 Aug 2018 07:59:51 -0500 Subject: [PATCH 34/52] bump rpm specfile to 1.31.47 --- 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 042abb40e..a91a3a78e 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -26,7 +26,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.31.45 +Version: 1.31.47 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons From 799b34eee8a2af20d76952d86b32d81317d0df39 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 10:34:54 -0400 Subject: [PATCH 35/52] handle xhr errors like when auth is no longer valid. Do a page refresh when this happens --- web/skins/classic/views/js/watch.js | 113 ++++++++++++++++------------ 1 file changed, 65 insertions(+), 48 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index c6a014f2b..7e8f868b3 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -114,6 +114,7 @@ if ( monitorType != 'WebSite' ) { method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', + onError: getStreamCmdError, onSuccess: getStreamCmdResponse, onFailure: getStreamCmdFailure } ); @@ -122,22 +123,28 @@ if ( monitorType != 'WebSite' ) { var streamStatus; -function getStreamCmdFailure(xhr) { -console.log(xhr); +function getStreamCmdError(text,error) { + console.log(error); + // Error are normally due to failed auth. reload the page. + window.location.reload(); } -function getStreamCmdResponse( respObj, respText ) { +function getStreamCmdFailure(xhr) { + console.log(xhr); +} +function getStreamCmdResponse(respObj, respText) { watchdogOk("stream"); + console.log('stream'); if ( streamCmdTimer ) - streamCmdTimer = clearTimeout( streamCmdTimer ); + streamCmdTimer = clearTimeout(streamCmdTimer); if ( respObj.result == 'Ok' ) { // The get status command can get backed up, in which case we won't be able to get the semaphore and will exit. if ( respObj.status ) { streamStatus = respObj.status; - $('fpsValue').set( 'text', streamStatus.fps ); + $('fpsValue').set('text', streamStatus.fps); - setAlarmState( streamStatus.state ); + setAlarmState(streamStatus.state); - $('levelValue').set( 'text', streamStatus.level ); + $('levelValue').set('text', streamStatus.level); if ( streamStatus.level > 95 ) $('levelValue').className = "alarm"; else if ( streamStatus.level > 80 ) @@ -145,34 +152,34 @@ function getStreamCmdResponse( respObj, respText ) { else $('levelValue').className = "ok"; - var delayString = secsToTime( streamStatus.delay ); + var delayString = secsToTime(streamStatus.delay); if ( streamStatus.paused == true ) { - $('modeValue').set( 'text', "Paused" ); - $('rate').addClass( 'hidden' ); - $('delayValue').set( 'text', delayString ); - $('delay').removeClass( 'hidden' ); - $('level').removeClass( 'hidden' ); - streamCmdPause( false ); + $('modeValue').set('text', 'Paused'); + $('rate').addClass('hidden'); + $('delayValue').set('text', delayString); + $('delay').removeClass('hidden'); + $('level').removeClass('hidden'); + streamCmdPause(false); } else if ( streamStatus.delayed == true ) { - $('modeValue').set( 'text', "Replay" ); - $('rateValue').set( 'text', streamStatus.rate ); - $('rate').removeClass( 'hidden' ); - $('delayValue').set( 'text', delayString ); - $('delay').removeClass( 'hidden' ); - $('level').removeClass( 'hidden' ); + $('modeValue').set('text', 'Replay'); + $('rateValue').set('text', streamStatus.rate); + $('rate').removeClass('hidden'); + $('delayValue').set('text', delayString); + $('delay').removeClass('hidden'); + $('level').removeClass('hidden'); if ( streamStatus.rate == 1 ) { - streamCmdPlay( false ); + streamCmdPlay(false); } else if ( streamStatus.rate > 0 ) { if ( streamStatus.rate < 1 ) - streamCmdSlowFwd( false ); + streamCmdSlowFwd(false); else - streamCmdFastFwd( false ); + streamCmdFastFwd(false); } else { if ( streamStatus.rate > -1 ) - streamCmdSlowRev( false ); + streamCmdSlowRev(false); else - streamCmdFastRev( false ); + streamCmdFastRev(false); } // rate } else { $('modeValue').set( 'text', "Live" ); @@ -209,16 +216,19 @@ function getStreamCmdResponse( respObj, respText ) { } // end if canEditMonitors if ( streamStatus.auth ) { - console.log("Haev a new auth hash" + streamStatus.auth); + console.log("Have a new auth hash" + streamStatus.auth); // Try to reload the image stream. var streamImg = $('liveStream'); if ( streamImg ) - streamImg.src = streamImg.src.replace( /auth=\w+/i, 'auth='+streamStatus.auth ); - } // end if haev a new auth hash + streamImg.src = streamImg.src.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + } // end if have a new auth hash } // end if respObj.status } else { - checkStreamForErrors("getStreamCmdResponse",respObj);//log them + checkStreamForErrors("getStreamCmdResponse", respObj);//log them // Try to reload the image stream. + // If it's an auth error, we should reload the whole page. + window.location.reload(); + if ( 0 ) { var streamImg = $('liveStream'+monitorId); if ( streamImg ) { streamImg.src = streamImg.src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) )); @@ -226,6 +236,7 @@ function getStreamCmdResponse( respObj, respText ) { } else { console.log("Unable to find streamImg liveStream"); } + } } var streamCmdTimeout = statusRefreshTimeout; @@ -360,14 +371,14 @@ if ( monitorType != 'WebSite' ) { var statusCmdTimer = null; } -function getStatusCmdResponse( respObj, respText ) { +function getStatusCmdResponse(respObj, respText) { watchdogOk("status"); if ( statusCmdTimer ) - statusCmdTimer = clearTimeout( statusCmdTimer ); + statusCmdTimer = clearTimeout(statusCmdTimer); if ( respObj.result == 'Ok' ) { - $('fpsValue').set( 'text', respObj.monitor.FrameRate ); - setAlarmState( respObj.monitor.Status ); + $('fpsValue').set('text', respObj.monitor.FrameRate); + setAlarmState(respObj.monitor.Status); } else checkStreamForErrors("getStatusCmdResponse", respObj); @@ -401,19 +412,19 @@ function getAlarmCmdResponse( respObj, respText ) { } function cmdDisableAlarms() { - alarmCmdReq.send( alarmCmdParms+"&command=disableAlarms" ); + alarmCmdReq.send(alarmCmdParms+"&command=disableAlarms"); } function cmdEnableAlarms() { - alarmCmdReq.send( alarmCmdParms+"&command=enableAlarms" ); + alarmCmdReq.send(alarmCmdParms+"&command=enableAlarms"); } function cmdForceAlarm() { - alarmCmdReq.send( alarmCmdParms+"&command=forceAlarm" ); + alarmCmdReq.send(alarmCmdParms+"&command=forceAlarm"); } function cmdCancelForcedAlarm() { - alarmCmdReq.send( alarmCmdParms+"&command=cancelForcedAlarm" ); + alarmCmdReq.send(alarmCmdParms+"&command=cancelForcedAlarm"); return false; } @@ -429,7 +440,13 @@ function getActResponse( respObj, respText ) { function deleteEvent( event, eventId ) { var actParms = "view=request&request=event&action=delete&id="+eventId; - var actReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: 3000, data: actParms, onSuccess: getActResponse } ); + var actReq = new Request.JSON( { + url: thisUrl, + method: 'post', + timeout: 3000, + data: actParms, + onSuccess: getActResponse + } ); actReq.send(); event.stop(); } @@ -444,7 +461,7 @@ if ( monitorType != 'WebSite' ) { } function highlightRow( row ) { - $(row).toggleClass( 'highlight' ); + $(row).toggleClass('highlight'); } function getEventCmdResponse( respObj, respText ) { @@ -649,7 +666,7 @@ var watchdogFunctions = { //Make sure the various refreshes are still taking effect function watchdogCheck( type ) { if ( watchdogInactive[type] ) { - console.log( "Detected streamWatch of type: " + type + " stopped, restarting" ); + console.log("Detected streamWatch of type: " + type + " stopped, restarting"); watchdogFunctions[type](); watchdogInactive[type] = false; } else { @@ -662,7 +679,7 @@ function watchdogOk( type ) { } function reloadWebSite() { - document.getElementById('imageFeed').innerHTML = document.getElementById('imageFeed').innerHTML; + document.getElementById('imageFeed').innerHTML = document.getElementById('imageFeed').innerHTML; } function initPage() { @@ -683,16 +700,16 @@ function initPage() { if ( !streamImg ) streamImg = $('imageFeed').getElement('object'); if ( streamMode == "single" ) { - streamImg.addEvent( 'click', fetchImage.pass( streamImg ) ); - fetchImage.pass( streamImg ).periodical( imageRefreshTimeout ); + streamImg.addEvent('click', fetchImage.pass(streamImg)); + fetchImage.pass(streamImg).periodical(imageRefreshTimeout); } else - streamImg.addEvent( 'click', function( event ) { handleClick( event ); } ); + streamImg.addEvent('click', function(event) { handleClick(event); }); } if ( refreshApplet && appletRefreshTime ) - appletRefresh.delay( appletRefreshTime*1000 ); - if (scale == "auto") changeScale(); - if (window.history.length == 1) { + appletRefresh.delay(appletRefreshTime*1000); + if ( scale == "auto" ) changeScale(); + if ( window.history.length == 1 ) { $j('#closeControl').html(''); } } else if ( monitorRefresh > 0 ) { @@ -701,4 +718,4 @@ function initPage() { } // Kick everything off -window.addEvent( 'domready', initPage ); +window.addEvent('domready', initPage); From 029c6401afe3eca2bfa9c3d9e547c0f863cff49e Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 31 Aug 2018 09:34:54 -0500 Subject: [PATCH 36/52] add libjson-maybexs-perl as a debian package dependency --- distros/debian/control | 2 +- distros/ubuntu1204/control | 1 + distros/ubuntu1410/control | 2 +- distros/ubuntu1504_cmake_split_packages/control | 2 +- distros/ubuntu1604/control | 1 + 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/distros/debian/control b/distros/debian/control index 29be56e25..20443f3f7 100644 --- a/distros/debian/control +++ b/distros/debian/control @@ -37,7 +37,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} , libphp-serialization-perl , libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, libdbd-mysql-perl , libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl - , libmodule-load-perl, libsys-mmap-perl, libjson-any-perl + , libmodule-load-perl, libsys-mmap-perl, libjson-any-perl, libjson-maybexs-perl , libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl , libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl , libsys-cpu-perl, libsys-meminfo-perl diff --git a/distros/ubuntu1204/control b/distros/ubuntu1204/control index febcb9435..f1756c5e8 100644 --- a/distros/ubuntu1204/control +++ b/distros/ubuntu1204/control @@ -50,6 +50,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,libdevice-serialport-perl ,libimage-info-perl ,libjson-any-perl + ,libjson-maybexs-perl ,libsys-mmap-perl [!hurd-any] ,liburi-encode-perl ,libwww-perl diff --git a/distros/ubuntu1410/control b/distros/ubuntu1410/control index 4f979f8c2..5a873f133 100644 --- a/distros/ubuntu1410/control +++ b/distros/ubuntu1410/control @@ -32,7 +32,7 @@ Package: libzoneminder-perl Section: perl Architecture: all Depends: ${misc:Depends}, ${perl:Depends}, libdbi-perl, - libdevice-serialport-perl, libimage-info-perl, libjson-any-perl, + libdevice-serialport-perl, libimage-info-perl, libjson-any-perl, libjson-maybexs-perl, libsys-mmap-perl, liburi-encode-perl, libwww-perl Description: Perl libraries for ZoneMinder ZoneMinder is a video camera security and surveillance solution. diff --git a/distros/ubuntu1504_cmake_split_packages/control b/distros/ubuntu1504_cmake_split_packages/control index 5f313897f..b24d67cf2 100644 --- a/distros/ubuntu1504_cmake_split_packages/control +++ b/distros/ubuntu1504_cmake_split_packages/control @@ -45,7 +45,7 @@ Package: libzoneminder-perl Section: perl Architecture: all Depends: ${misc:Depends}, ${perl:Depends}, libdbi-perl, - libdevice-serialport-perl, libimage-info-perl, libjson-any-perl, + libdevice-serialport-perl, libimage-info-perl, libjson-any-perl, libjson-maybexs-perl, libsys-mmap-perl, liburi-encode-perl, libwww-perl Description: Perl libraries for ZoneMinder ZoneMinder is a video camera security and surveillance solution. diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index 3054a2d55..d4fe74e79 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -53,6 +53,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,libdevice-serialport-perl ,libimage-info-perl ,libjson-any-perl + ,libjson-maybexs-perl ,libsys-mmap-perl [!hurd-any] ,liburi-encode-perl ,libwww-perl From 4b30ea78779632f9c5cb5ea15fb56d2ea53513c2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 10:35:23 -0400 Subject: [PATCH 37/52] cleanup, whitespace --- web/includes/actions.php | 460 ++++++++++++++++++++------------------- 1 file changed, 242 insertions(+), 218 deletions(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index cd67fc81c..de0861fe0 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -29,16 +29,16 @@ function do_request($method, $url, $data=array(), $optional_headers = null) { 'method' => $method, 'content' => $data )); - if ($optional_headers !== null) { + if ( $optional_headers !== null ) { $params['http']['header'] = $optional_headers; } $ctx = stream_context_create($params); $fp = @fopen($url, 'rb', false, $ctx); - if (!$fp) { + if ( !$fp ) { throw new Exception("Problem with $url, $php_errormsg"); } $response = @stream_get_contents($fp); - if ($response === false) { + if ( $response === false ) { throw new Exception("Problem reading data from $url, $php_errormsg"); } return $response; @@ -49,16 +49,16 @@ function do_post_request($url, $data, $optional_headers = null) { 'method' => 'POST', 'content' => $data )); - if ($optional_headers !== null) { + if ( $optional_headers !== null ) { $params['http']['header'] = $optional_headers; } $ctx = stream_context_create($params); $fp = @fopen($url, 'rb', false, $ctx); - if (!$fp) { + if ( !$fp ) { throw new Exception("Problem with $url, $php_errormsg"); } $response = @stream_get_contents($fp); - if ($response === false) { + if ( $response === false ) { throw new Exception("Problem reading data from $url, $php_errormsg"); } return $response; @@ -106,17 +106,17 @@ if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 're $responseData = json_decode($res,true); // PP - credit: https://github.com/google/recaptcha/blob/master/src/ReCaptcha/Response.php // if recaptcha resulted in error, we might have to deny login - if (isset($responseData['success']) && $responseData['success'] == false) { + if ( isset($responseData['success']) && $responseData['success'] == false ) { // PP - before we deny auth, let's make sure the error was not 'invalid secret' // because that means the user did not configure the secret key correctly // in this case, we prefer to let him login in and display a message to correct // the key. Unfortunately, there is no way to check for invalid site key in code // as it produces the same error as when you don't answer a recaptcha - if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) { - if (!in_array('invalid-input-secret',$responseData['error-codes'])) { + if ( isset($responseData['error-codes']) && is_array($responseData['error-codes']) ) { + if ( !in_array('invalid-input-secret',$responseData['error-codes']) ) { Error('reCaptcha authentication failed'); userLogout(); - $view='login'; + $view = 'login'; $refreshParent = true; return; } else { @@ -140,19 +140,19 @@ if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 're $view = 'none'; } else if ( $action == 'bandwidth' && isset($_REQUEST['newBandwidth']) ) { $_COOKIE['zmBandwidth'] = validStr($_REQUEST['newBandwidth']); - setcookie( 'zmBandwidth', validStr($_REQUEST['newBandwidth']), time()+3600*24*30*12*10 ); + setcookie('zmBandwidth', validStr($_REQUEST['newBandwidth']), time()+3600*24*30*12*10); $refreshParent = true; } // Event scope actions, view permissions only required if ( canView('Events') ) { - if ( isset( $_REQUEST['object'] ) and ( $_REQUEST['object'] == 'filter' ) ) { + if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) { if ( $action == 'addterm' ) { - $_REQUEST['filter'] = addFilterTerm( $_REQUEST['filter'], $_REQUEST['line'] ); + $_REQUEST['filter'] = addFilterTerm($_REQUEST['filter'], $_REQUEST['line']); } elseif ( $action == 'delterm' ) { - $_REQUEST['filter'] = delFilterTerm( $_REQUEST['filter'], $_REQUEST['line'] ); - } else if ( canEdit( 'Events' ) ) { + $_REQUEST['filter'] = delFilterTerm($_REQUEST['filter'], $_REQUEST['line']); + } else if ( canEdit('Events') ) { if ( $action == 'delete' ) { if ( ! empty($_REQUEST['Id']) ) { dbQuery('DELETE FROM Filters WHERE Id=?', array($_REQUEST['Id'])); @@ -210,11 +210,13 @@ if ( canView('Events') ) { dbQuery('UPDATE Events SET Name=? WHERE Id=?', array($_REQUEST['eventName'], $_REQUEST['eid'])); } else if ( $action == 'eventdetail' ) { if ( !empty($_REQUEST['eid']) ) { - dbQuery( 'UPDATE Events SET Cause=?, Notes=? WHERE Id=?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['eid'] ) ); + dbQuery('UPDATE Events SET Cause=?, Notes=? WHERE Id=?', + array($_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['eid']) ); } else { $dbConn->beginTransaction(); foreach( getAffectedIds('markEid') as $markEid ) { - dbQuery( 'UPDATE Events SET Cause=?, Notes=? WHERE Id=?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $markEid ) ); + dbQuery('UPDATE Events SET Cause=?, Notes=? WHERE Id=?', + array($_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $markEid) ); } $dbConn->commit(); } @@ -226,7 +228,7 @@ if ( canView('Events') ) { dbQuery('UPDATE Events SET Archived=? WHERE Id=?', array($archiveVal, $_REQUEST['eid'])); } else { $dbConn->beginTransaction(); - foreach( getAffectedIds( 'markEid' ) as $markEid ) { + foreach( getAffectedIds('markEid') as $markEid ) { dbQuery('UPDATE Events SET Archived=? WHERE Id=?', array($archiveVal, $markEid)); } $dbConn->commit(); @@ -234,8 +236,8 @@ if ( canView('Events') ) { } } elseif ( $action == 'delete' ) { $dbConn->beginTransaction(); - foreach( getAffectedIds( 'markEid' ) as $markEid ) { - deleteEvent( $markEid ); + foreach( getAffectedIds('markEid') as $markEid ) { + deleteEvent($markEid); } $dbConn->commit(); $refreshParent = true; @@ -245,45 +247,47 @@ if ( canView('Events') ) { } // end canView(Events) // Monitor control actions, require a monitor id and control view permissions for that monitor -if ( !empty($_REQUEST['mid']) && canView( 'Control', $_REQUEST['mid'] ) ) { - require_once( 'control_functions.php' ); - require_once( 'Monitor.php' ); +if ( !empty($_REQUEST['mid']) && canView('Control', $_REQUEST['mid']) ) { + require_once('control_functions.php'); + require_once('Monitor.php'); $mid = validInt($_REQUEST['mid']); if ( $action == 'control' ) { - $monitor = new Monitor( $mid ); + $monitor = new Monitor($mid); - $ctrlCommand = buildControlCommand( $monitor ); - sendControlCommand( $monitor->Id(), $ctrlCommand ); - } elseif ( $action == 'settings' ) { + $ctrlCommand = buildControlCommand($monitor); + sendControlCommand($monitor->Id(), $ctrlCommand); + } else if ( $action == 'settings' ) { $args = ' -m ' . escapeshellarg($mid); $args .= ' -B' . escapeshellarg($_REQUEST['newBrightness']); $args .= ' -C' . escapeshellarg($_REQUEST['newContrast']); $args .= ' -H' . escapeshellarg($_REQUEST['newHue']); $args .= ' -O' . escapeshellarg($_REQUEST['newColour']); - $zmuCommand = getZmuCommand( $args ); + $zmuCommand = getZmuCommand($args); - $zmuOutput = exec( $zmuCommand ); - list( $brightness, $contrast, $hue, $colour ) = explode( ' ', $zmuOutput ); - dbQuery( 'UPDATE Monitors SET Brightness = ?, Contrast = ?, Hue = ?, Colour = ? WHERE Id = ?', array($brightness, $contrast, $hue, $colour, $mid)); + $zmuOutput = exec($zmuCommand); + list($brightness, $contrast, $hue, $colour) = explode(' ', $zmuOutput); + dbQuery( + 'UPDATE Monitors SET Brightness = ?, Contrast = ?, Hue = ?, Colour = ? WHERE Id = ?', + array($brightness, $contrast, $hue, $colour, $mid)); } } // Control capability actions, require control edit permissions if ( canEdit('Control') ) { if ( $action == 'controlcap' ) { - require_once( 'Control.php' ); + require_once('Control.php'); $Control = new Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null ); //$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns ); - $Control->save( $_REQUEST['newControl'] ); + $Control->save($_REQUEST['newControl']); $refreshParent = true; $view = 'none'; } elseif ( $action == 'delete' ) { if ( isset($_REQUEST['markCids']) ) { foreach( $_REQUEST['markCids'] as $markCid ) { - dbQuery( 'delete from Controls where Id = ?', array($markCid) ); - dbQuery( 'update Monitors set Controllable = 0, ControlId = 0 where ControlId = ?', array($markCid) ); + dbQuery('DELETE FROM Controls WHERE Id = ?', array($markCid)); + dbQuery('UPDATE Monitors SET Controllable = 0, ControlId = 0 WHERE ControlId = ?', array($markCid)); $refreshParent = true; } } @@ -293,59 +297,59 @@ if ( canEdit('Control') ) { if ( isset($_REQUEST['object']) and $_REQUEST['object'] == 'Monitor' ) { if ( $action == 'save' ) { foreach ( $_REQUEST['mids'] as $mid ) { - $mid = ValidInt( $mid ); - if ( ! canEdit('Monitors', $mid ) ) { + $mid = ValidInt($mid); + if ( ! canEdit('Monitors', $mid) ) { Warning("Cannot edit monitor $mid"); continue; } - $Monitor = new Monitor( $mid ); + $Monitor = new Monitor($mid); if ( $Monitor->Type() != 'WebSite' ) { $Monitor->zmaControl('stop'); $Monitor->zmcControl('stop'); } - $Monitor->save( $_REQUEST['newMonitor'] ); - if ($Monitor->Function() != 'None' && $Monitor->Type() != 'WebSite' ) { + $Monitor->save($_REQUEST['newMonitor']); + if ( $Monitor->Function() != 'None' && $Monitor->Type() != 'WebSite' ) { $Monitor->zmcControl('start'); if ( $Monitor->Enabled() ) { $Monitor->zmaControl('start'); } } - } // end foreach mid $refreshParent = true; } // end if action == save } // end if object is Monitor // Monitor edit actions, require a monitor id and edit permissions for that monitor -if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) { +if ( !empty($_REQUEST['mid']) && canEdit('Monitors', $_REQUEST['mid']) ) { $mid = validInt($_REQUEST['mid']); if ( $action == 'function' ) { - $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array($mid) ); + $monitor = dbFetchOne('SELECT * FROM Monitors WHERE Id=?', NULL, array($mid)); $newFunction = validStr($_REQUEST['newFunction']); # Because we use a checkbox, it won't get passed in the request. So not being in _REQUEST means 0 - $newEnabled = ( !isset( $_REQUEST['newEnabled'] ) or $_REQUEST['newEnabled'] != '1' ) ? '0' : '1'; + $newEnabled = ( !isset($_REQUEST['newEnabled']) or $_REQUEST['newEnabled'] != '1' ) ? '0' : '1'; $oldFunction = $monitor['Function']; $oldEnabled = $monitor['Enabled']; if ( $newFunction != $oldFunction || $newEnabled != $oldEnabled ) { - dbQuery( 'UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?', array( $newFunction, $newEnabled, $mid ) ); + dbQuery('UPDATE Monitors SET Function=?, Enabled=? WHERE Id=?', + array($newFunction, $newEnabled, $mid)); $monitor['Function'] = $newFunction; $monitor['Enabled'] = $newEnabled; - if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) { + if ( daemonCheck() && ($monitor['Type'] != 'WebSite') ) { $restart = ($oldFunction == 'None') || ($newFunction == 'None') || ($newEnabled != $oldEnabled); - zmaControl( $monitor, 'stop' ); - zmcControl( $monitor, $restart?'restart':'' ); - zmaControl( $monitor, 'start' ); + zmaControl($monitor, 'stop'); + zmcControl($monitor, $restart?'restart':''); + zmaControl($monitor, 'start'); } $refreshParent = true; } - } elseif ( $action == 'zone' && isset( $_REQUEST['zid'] ) ) { + } else if ( $action == 'zone' && isset($_REQUEST['zid']) ) { $zid = validInt($_REQUEST['zid']); - $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array($mid) ); + $monitor = dbFetchOne('SELECT * FROM Monitors WHERE Id=?', NULL, array($mid)); if ( !empty($zid) ) { - $zone = dbFetchOne( 'SELECT * FROM Zones WHERE MonitorId=? AND Id=?', NULL, array( $mid, $zid ) ); + $zone = dbFetchOne('SELECT * FROM Zones WHERE MonitorId=? AND Id=?', NULL, array($mid, $zid)); } else { $zone = array(); } @@ -365,74 +369,74 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) { unset( $_REQUEST['newZone']['Points'] ); $types = array(); - $changes = getFormChanges( $zone, $_REQUEST['newZone'], $types ); + $changes = getFormChanges($zone, $_REQUEST['newZone'], $types); - if ( count( $changes ) ) { + if ( count($changes) ) { if ( $zid > 0 ) { - dbQuery( 'UPDATE Zones SET '.implode( ', ', $changes ).' WHERE MonitorId=? AND Id=?', array( $mid, $zid) ); + dbQuery('UPDATE Zones SET '.implode(', ', $changes).' WHERE MonitorId=? AND Id=?', array($mid, $zid)); } else { - dbQuery( 'INSERT INTO Zones SET MonitorId=?, '.implode( ', ', $changes ), array( $mid ) ); + dbQuery('INSERT INTO Zones SET MonitorId=?, '.implode(', ', $changes), array($mid)); } - if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) { + if ( daemonCheck() && ($monitor['Type'] != 'WebSite') ) { if ( $_REQUEST['newZone']['Type'] == 'Privacy' ) { - zmaControl( $monitor, 'stop' ); - zmcControl( $monitor, 'restart' ); - zmaControl( $monitor, 'start' ); + zmaControl($monitor, 'stop'); + zmcControl($monitor, 'restart'); + zmaControl($monitor, 'start'); } else { - zmaControl( $mid, 'restart' ); + zmaControl($monitor, 'restart'); } } - if ( $_REQUEST['newZone']['Type'] == 'Privacy' && $monitor['Controllable'] ) { - require_once( 'control_functions.php' ); - sendControlCommand( $mid, 'quit' ); + if ( ($_REQUEST['newZone']['Type'] == 'Privacy') && $monitor['Controllable'] ) { + require_once('control_functions.php'); + sendControlCommand($mid, 'quit'); } $refreshParent = true; } $view = 'none'; - } elseif ( $action == 'plugin' && isset($_REQUEST['pl'])) { - $sql='SELECT * FROM PluginsConfig WHERE MonitorId=? AND ZoneId=? AND pluginName=?'; - $pconfs=dbFetchAll( $sql, NULL, array( $mid, $_REQUEST['zid'], $_REQUEST['pl'] ) ); - $changes=0; - foreach( $pconfs as $pconf ) { - $value=$_REQUEST['pluginOpt'][$pconf['Name']]; - if(array_key_exists($pconf['Name'], $_REQUEST['pluginOpt']) && ($pconf['Value']!=$value)) { - dbQuery('UPDATE PluginsConfig SET Value=? WHERE id=?', array( $value, $pconf['Id'] ) ); + } elseif ( $action == 'plugin' && isset($_REQUEST['pl']) ) { + $sql = 'SELECT * FROM PluginsConfig WHERE MonitorId=? AND ZoneId=? AND pluginName=?'; + $pconfs=dbFetchAll($sql, NULL, array($mid, $_REQUEST['zid'], $_REQUEST['pl'])); + $changes = 0; + foreach ( $pconfs as $pconf ) { + $value = $_REQUEST['pluginOpt'][$pconf['Name']]; + if ( array_key_exists($pconf['Name'], $_REQUEST['pluginOpt']) && ($pconf['Value'] != $value) ) { + dbQuery('UPDATE PluginsConfig SET Value=? WHERE id=?', array($value, $pconf['Id'])); $changes++; } } - if($changes>0) { - if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) { - zmaControl( $mid, 'restart' ); + if ( $changes > 0 ) { + if ( daemonCheck() && ($monitor['Type'] != 'WebSite') ) { + zmaControl($mid, 'restart'); } $refreshParent = true; } $view = 'none'; - } elseif ( $action == 'sequence' && isset($_REQUEST['smid']) ) { + } elseif ( ($action == 'sequence') && isset($_REQUEST['smid']) ) { $smid = validInt($_REQUEST['smid']); - $monitor = dbFetchOne( 'select * from Monitors where Id = ?', NULL, array($mid) ); - $smonitor = dbFetchOne( 'select * from Monitors where Id = ?', NULL, array($smid) ); + $monitor = dbFetchOne('SELECT * FROM Monitors WHERE Id = ?', NULL, array($mid)); + $smonitor = dbFetchOne('SELECT * FROM Monitors WHERE Id = ?', NULL, array($smid)); - dbQuery( 'update Monitors set Sequence=? where Id=?', array( $smonitor['Sequence'], $monitor['Id'] ) ); - dbQuery( 'update Monitors set Sequence=? WHERE Id=?', array( $monitor['Sequence'], $smonitor['Id'] ) ); + dbQuery('UPDATE Monitors SET Sequence=? WHERE Id=?', array($smonitor['Sequence'], $monitor['Id'])); + dbQuery('UPDATE Monitors SET Sequence=? WHERE Id=?', array($monitor['Sequence'], $smonitor['Id'])); $refreshParent = true; fixSequences(); } elseif ( $action == 'delete' ) { if ( isset($_REQUEST['markZids']) ) { $deletedZid = 0; - foreach( $_REQUEST['markZids'] as $markZid ) { - $zone = dbFetchOne( 'select * from Zones where Id=?', NULL, array($markZid) ); - dbQuery( 'delete from Zones WHERE MonitorId=? AND Id=?', array( $mid, $markZid) ); + foreach ( $_REQUEST['markZids'] as $markZid ) { + $zone = dbFetchOne('SELECT * FROM Zones WHERE Id=?', NULL, array($markZid)); + dbQuery('DELETE FROM Zones WHERE MonitorId=? AND Id=?', array($mid, $markZid)); $deletedZid = 1; } if ( $deletedZid ) { if ( daemonCheck() && $monitor['Type'] != 'WebSite' ) { if ( $zone['Type'] == 'Privacy' ) { - zmaControl( $mid, 'stop' ); - zmcControl( $mid, 'restart' ); - zmaControl( $mid, 'start' ); + zmaControl($mid, 'stop'); + zmcControl($mid, 'restart'); + zmaControl($mid, 'start'); } else { - zmaControl( $mid, 'restart' ); + zmaControl($mid, 'restart'); } } // end if daemonCheck() $refreshParent = true; @@ -442,15 +446,15 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) { } // end if $mid and canEdit($mid) // Monitor edit actions, monitor id derived, require edit permissions for that monitor -if ( canEdit( 'Monitors' ) ) { +if ( canEdit('Monitors') ) { if ( $action == 'monitor' ) { $mid = 0; if ( !empty($_REQUEST['mid']) ) { $mid = validInt($_REQUEST['mid']); - $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array($mid) ); + $monitor = dbFetchOne('SELECT * FROM Monitors WHERE Id=?', NULL, array($mid)); if ( ZM_OPT_X10 ) { - $x10Monitor = dbFetchOne( 'SELECT * FROM TriggersX10 WHERE MonitorId=?', NULL, array($mid) ); + $x10Monitor = dbFetchOne('SELECT * FROM TriggersX10 WHERE MonitorId=?', NULL, array($mid)); if ( !$x10Monitor ) $x10Monitor = array(); } @@ -476,18 +480,19 @@ if ( canEdit( 'Monitors' ) ) { ); if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) { - $_REQUEST['newMonitor']['ServerId'] = dbFetchOne('SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id'); - Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] ); + $_REQUEST['newMonitor']['ServerId'] = dbFetchOne( + 'SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id'); + Logger::Debug('Auto selecting server: Got ' . $_REQUEST['newMonitor']['ServerId'] ); if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) { $_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID; - Logger::Debug("Auto selecting server to " . ZM_SERVER_ID); + Logger::Debug('Auto selecting server to ' . ZM_SERVER_ID); } } $columns = getTableColumns('Monitors'); $changes = getFormChanges($monitor, $_REQUEST['newMonitor'], $types, $columns); - if ( count( $changes ) ) { + if ( count($changes) ) { if ( $mid ) { # If we change anything that changes the shared mem size, zma can complain. So let's stop first. @@ -495,19 +500,19 @@ if ( canEdit( 'Monitors' ) ) { zmaControl($monitor, 'stop'); zmcControl($monitor, 'stop'); } - dbQuery( 'UPDATE Monitors SET '.implode( ', ', $changes ).' WHERE Id=?', array($mid) ); + dbQuery('UPDATE Monitors SET '.implode(', ', $changes).' WHERE Id=?', array($mid)); // Groups will be added below if ( isset($changes['Name']) or isset($changes['StorageId']) ) { - $OldStorage = new Storage( $monitor['StorageId'] ); - $saferOldName = basename( $monitor['Name'] ); - if ( file_exists( $OldStorage->Path().'/'.$saferOldName ) ) - unlink( $OldStorage->Path().'/'.$saferOldName ); + $OldStorage = new Storage($monitor['StorageId']); + $saferOldName = basename($monitor['Name']); + if ( file_exists($OldStorage->Path().'/'.$saferOldName) ) + unlink($OldStorage->Path().'/'.$saferOldName); - $NewStorage = new Storage( $_REQUEST['newMonitor']['StorageId'] ); - if ( ! file_exists( $NewStorage->Path().'/'.$mid ) ) - mkdir( $NewStorage->Path().'/'.$mid, 0755 ); - $saferNewName = basename( $_REQUEST['newMonitor']['Name'] ); - symlink( $mid, $NewStorage->Path().'/'.$saferNewName ); + $NewStorage = new Storage($_REQUEST['newMonitor']['StorageId']); + if ( ! file_exists($NewStorage->Path().'/'.$mid) ) + mkdir($NewStorage->Path().'/'.$mid, 0755); + $saferNewName = basename($_REQUEST['newMonitor']['Name']); + symlink($mid, $NewStorage->Path().'/'.$saferNewName); } if ( isset($changes['Width']) || isset($changes['Height']) ) { $newW = $_REQUEST['newMonitor']['Width']; @@ -517,15 +522,15 @@ if ( canEdit( 'Monitors' ) ) { $oldH = $monitor['Height']; $oldA = $oldW * $oldH; - $zones = dbFetchAll( 'SELECT * FROM Zones WHERE MonitorId=?', NULL, array($mid) ); + $zones = dbFetchAll('SELECT * FROM Zones WHERE MonitorId=?', NULL, array($mid)); foreach ( $zones as $zone ) { $newZone = $zone; - $points = coordsToPoints( $zone['Coords'] ); + $points = coordsToPoints($zone['Coords']); for ( $i = 0; $i < count($points); $i++ ) { $points[$i]['x'] = intval(($points[$i]['x']*($newW-1))/($oldW-1)); $points[$i]['y'] = intval(($points[$i]['y']*($newH-1))/($oldH-1)); } - $newZone['Coords'] = pointsToCoords( $points ); + $newZone['Coords'] = pointsToCoords($points); $newZone['Area'] = intval(round(($zone['Area']*$newA)/$oldA)); $newZone['MinAlarmPixels'] = intval(round(($newZone['MinAlarmPixels']*$newA)/$oldA)); $newZone['MaxAlarmPixels'] = intval(round(($newZone['MaxAlarmPixels']*$newA)/$oldA)); @@ -534,41 +539,43 @@ if ( canEdit( 'Monitors' ) ) { $newZone['MinBlobPixels'] = intval(round(($newZone['MinBlobPixels']*$newA)/$oldA)); $newZone['MaxBlobPixels'] = intval(round(($newZone['MaxBlobPixels']*$newA)/$oldA)); - $changes = getFormChanges( $zone, $newZone, $types ); + $changes = getFormChanges($zone, $newZone, $types); - if ( count( $changes ) ) { - dbQuery( 'update Zones set '.implode( ', ', $changes ).' WHERE MonitorId=? AND Id=?', array( $mid, $zone['Id'] ) ); + if ( count($changes) ) { + dbQuery('UPDATE Zones SET '.implode(', ', $changes).' WHERE MonitorId=? AND Id=?', + array($mid, $zone['Id'])); } - } - } + } // end foreach zone + } // end if width and height $restart = true; - } else if ( ! $user['MonitorIds'] ) { // Can only create new monitors if we are not restricted to specific monitors + } else if ( ! $user['MonitorIds'] ) { + // Can only create new monitors if we are not restricted to specific monitors # FIXME This is actually a race condition. Should lock the table. $maxSeq = dbFetchOne('SELECT MAX(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence'); $changes[] = 'Sequence = '.($maxSeq+1); - if ( dbQuery( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ) ) { + if ( dbQuery('INSERT INTO Monitors SET '.implode(', ', $changes)) ) { $mid = dbInsertId(); $zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height']; - dbQuery( "insert into Zones set MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) ); + dbQuery("INSERT INTO Zones SET MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) ); //$view = 'none'; - $Storage = new Storage( $_REQUEST['newMonitor']['StorageId'] ); - mkdir( $Storage->Path().'/'.$mid, 0755 ); + $Storage = new Storage($_REQUEST['newMonitor']['StorageId']); + mkdir($Storage->Path().'/'.$mid, 0755); $saferName = basename($_REQUEST['newMonitor']['Name']); - symlink( $mid, $Storage->Path().'/'.$saferName ); + symlink($mid, $Storage->Path().'/'.$saferName); } else { - Error("Error saving new Monitor."); + Error('Error saving new Monitor.'); return; } } else { - Error("Users with Monitors restrictions cannot create new monitors."); + Error('Users with Monitors restrictions cannot create new monitors.'); return; } $restart = true; } else { - Logger::Debug("No action due to no changes to Monitor"); + Logger::Debug('No action due to no changes to Monitor'); } # end if count(changes) if ( @@ -589,21 +596,21 @@ if ( canEdit( 'Monitors' ) ) { } // end if there has been a change of groups if ( ZM_OPT_X10 ) { - $x10Changes = getFormChanges( $x10Monitor, $_REQUEST['newX10Monitor'] ); + $x10Changes = getFormChanges($x10Monitor, $_REQUEST['newX10Monitor']); - if ( count( $x10Changes ) ) { + if ( count($x10Changes) ) { if ( $x10Monitor && isset($_REQUEST['newX10Monitor']) ) { - dbQuery( 'update TriggersX10 set '.implode( ', ', $x10Changes ).' where MonitorId=?', array($mid) ); + dbQuery('UPDATE TriggersX10 SET '.implode(', ', $x10Changes).' WHERE MonitorId=?', array($mid)); } elseif ( !$user['MonitorIds'] ) { if ( !$x10Monitor ) { - dbQuery( 'insert into TriggersX10 set MonitorId = ?, '.implode( ', ', $x10Changes ), array( $mid ) ); + dbQuery('INSERT INTO TriggersX10 SET MonitorId = ?, '.implode(', ', $x10Changes), array($mid)); } else { - dbQuery( 'delete from TriggersX10 where MonitorId = ?', array($mid) ); + dbQuery('DELETE FROM TriggersX10 WHERE MonitorId = ?', array($mid)); } } $restart = true; - } - } + } # end if has x10Changes + } # end if ZM_OPT_X10 if ( $restart ) { @@ -616,8 +623,8 @@ if ( canEdit( 'Monitors' ) ) { } if ( $new_monitor->Controllable() ) { - require_once( 'control_functions.php' ); - sendControlCommand( $mid, 'quit' ); + require_once('control_functions.php'); + sendControlCommand($mid, 'quit'); } // really should thump zmwatch and maybe zmtrigger too. //daemonControl( 'restart', 'zmwatch.pl' ); @@ -626,11 +633,11 @@ if ( canEdit( 'Monitors' ) ) { $view = 'none'; } elseif ( $action == 'delete' ) { if ( isset($_REQUEST['markMids']) && !$user['MonitorIds'] ) { - require_once( 'Monitor.php' ); - foreach( $_REQUEST['markMids'] as $markMid ) { + require_once('Monitor.php'); + foreach ( $_REQUEST['markMids'] as $markMid ) { if ( canEdit('Monitors', $markMid) ) { // This could be faster as a select all - if ( $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id = ?', NULL, array($markMid) ) ) { + if ( $monitor = dbFetchOne('SELECT * FROM Monitors WHERE Id = ?', NULL, array($markMid)) ) { $Monitor = new Monitor($monitor); $Monitor->delete(); } // end if monitor found in db @@ -641,15 +648,17 @@ if ( canEdit( 'Monitors' ) ) { } // Device view actions -if ( canEdit( 'Devices' ) ) { +if ( canEdit('Devices') ) { if ( $action == 'device' ) { if ( !empty($_REQUEST['command']) ) { - setDeviceStatusX10( $_REQUEST['key'], $_REQUEST['command'] ); - } elseif ( isset( $_REQUEST['newDevice'] ) ) { + setDeviceStatusX10($_REQUEST['key'], $_REQUEST['command']); + } else if ( isset($_REQUEST['newDevice']) ) { if ( isset($_REQUEST['did']) ) { - dbQuery( 'update Devices set Name=?, KeyString=? where Id=?', array($_REQUEST['newDevice']['Name'], $_REQUEST['newDevice']['KeyString'], $_REQUEST['did']) ); + dbQuery('UPDATE Devices SET Name=?, KeyString=? WHERE Id=?', + array($_REQUEST['newDevice']['Name'], $_REQUEST['newDevice']['KeyString'], $_REQUEST['did']) ); } else { - dbQuery( 'insert into Devices set Name=?, KeyString=?', array( $_REQUEST['newDevice']['Name'], $_REQUEST['newDevice']['KeyString'] ) ); + dbQuery('INSERT INTO Devices SET Name=?, KeyString=?', + array($_REQUEST['newDevice']['Name'], $_REQUEST['newDevice']['KeyString']) ); } $refreshParent = true; $view = 'none'; @@ -657,7 +666,7 @@ if ( canEdit( 'Devices' ) ) { } elseif ( $action == 'delete' ) { if ( isset($_REQUEST['markDids']) ) { foreach( $_REQUEST['markDids'] as $markDid ) { - dbQuery( 'delete from Devices where Id=?', array($markDid) ); + dbQuery('DELETE FROM Devices WHERE Id=?', array($markDid)); $refreshParent = true; } } @@ -665,47 +674,59 @@ if ( canEdit( 'Devices' ) ) { } // end if canedit devices // Group view actions -if ( canView( 'Groups' ) && $action == 'setgroup' ) { +if ( canView('Groups') && ($action == 'setgroup') ) { if ( !empty($_REQUEST['gid']) ) { - setcookie( 'zmGroup', validInt($_REQUEST['gid']), time()+3600*24*30*12*10 ); + setcookie('zmGroup', validInt($_REQUEST['gid']), time()+3600*24*30*12*10); } else { - setcookie( 'zmGroup', '', time()-3600*24*2 ); + setcookie('zmGroup', '', time()-3600*24*2); } $refreshParent = true; } // Group edit actions -# Should probably verify that each monitor id is a valid monitor, that we have access to. However at the moment, you have to have System permissions to do this -if ( canEdit( 'Groups' ) ) { +# Should probably verify that each monitor id is a valid monitor, that we have access to. +# However at the moment, you have to have System permissions to do this +if ( canEdit('Groups') ) { if ( $action == 'group' ) { - $monitors = empty( $_POST['newGroup']['MonitorIds'] ) ? '' : implode(',', $_POST['newGroup']['MonitorIds']); + $monitors = empty($_POST['newGroup']['MonitorIds']) ? '' : implode(',', $_POST['newGroup']['MonitorIds']); $group_id = null; if ( !empty($_POST['gid']) ) { $group_id = $_POST['gid']; - dbQuery( 'UPDATE Groups SET Name=?, ParentId=? WHERE Id=?', - array($_POST['newGroup']['Name'], ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), $group_id) ); - dbQuery( 'DELETE FROM Groups_Monitors WHERE GroupId=?', array($group_id) ); + dbQuery( + 'UPDATE Groups SET Name=?, ParentId=? WHERE Id=?', + array( + $_POST['newGroup']['Name'], + ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), + $group_id, + ) + ); + dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($group_id)); } else { - dbQuery( 'INSERT INTO Groups (Name,ParentId) VALUES (?,?)', - array( $_POST['newGroup']['Name'], ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ) ) ); - $group_id=dbInsertId(); + dbQuery( + 'INSERT INTO Groups (Name,ParentId) VALUES (?,?)', + array( + $_POST['newGroup']['Name'], + ( $_POST['newGroup']['ParentId'] == '' ? null : $_POST['newGroup']['ParentId'] ), + ) + ); + $group_id = dbInsertId(); } if ( $group_id ) { foreach ( $_POST['newGroup']['MonitorIds'] as $mid ) { - dbQuery( 'INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid) ); + dbQuery('INSERT INTO Groups_Monitors (GroupId,MonitorId) VALUES (?,?)', array($group_id, $mid)); } } $view = 'none'; $refreshParent = true; } else if ( $action == 'delete' ) { if ( !empty($_REQUEST['gid']) ) { - if ( is_array( $_REQUEST['gid'] ) ) { - foreach( $_REQUEST['gid'] as $gid ) { - $Group = new Group( $gid ); + if ( is_array($_REQUEST['gid']) ) { + foreach ( $_REQUEST['gid'] as $gid ) { + $Group = new Group($gid); $Group->delete(); } } else { - $Group = new Group( $_REQUEST['gid'] ); + $Group = new Group($_REQUEST['gid'] ); $Group->delete(); } } @@ -714,23 +735,23 @@ if ( canEdit( 'Groups' ) ) { } // end if can edit groups // System edit actions -if ( canEdit( 'System' ) ) { - if ( isset( $_REQUEST['object'] ) ) { +if ( canEdit('System') ) { + if ( isset($_REQUEST['object']) ) { if ( $_REQUEST['object'] == 'MontageLayout' ) { require_once('MontageLayout.php'); if ( $action == 'Save' ) { $Layout = null; if ( $_REQUEST['Name'] != '' ) { $Layout = new MontageLayout(); - $Layout->Name( $_REQUEST['Name'] ); + $Layout->Name($_REQUEST['Name']); } else { - $Layout = new MontageLayout( $_REQUEST['zmMontageLayout'] ); + $Layout = new MontageLayout($_REQUEST['zmMontageLayout']); } - $Layout->Positions( $_REQUEST['Positions'] ); + $Layout->Positions($_REQUEST['Positions']); $Layout->save(); session_start(); $_SESSION['zmMontageLayout'] = $Layout->Id(); - setcookie('zmMontageLayout', $Layout->Id(), 1 ); + setcookie('zmMontageLayout', $Layout->Id(), 1); session_write_close(); $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montagereview'; } // end if save @@ -738,19 +759,24 @@ if ( canEdit( 'System' ) ) { } else if ( $_REQUEST['object'] == 'server' ) { if ( $action == 'Save' ) { - if ( !empty($_REQUEST['id']) ) - $dbServer = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array($_REQUEST['id']) ); - else + if ( !empty($_REQUEST['id']) ) { + $dbServer = dbFetchOne( + 'SELECT * FROM Servers WHERE Id=?', + NULL, + array($_REQUEST['id']) ); + } else { $dbServer = array(); + } $types = array(); - $changes = getFormChanges( $dbServer, $_REQUEST['newServer'], $types ); + $changes = getFormChanges($dbServer, $_REQUEST['newServer'], $types); - if ( count( $changes ) ) { + if ( count($changes) ) { if ( !empty($_REQUEST['id']) ) { - dbQuery( 'UPDATE Servers SET '.implode( ', ', $changes ).' WHERE Id = ?', array($_REQUEST['id']) ); + dbQuery('UPDATE Servers SET '.implode(', ', $changes).' WHERE Id = ?', + array($_REQUEST['id']) ); } else { - dbQuery( 'INSERT INTO Servers set '.implode( ', ', $changes ) ); + dbQuery('INSERT INTO Servers SET '.implode(', ', $changes)); } $refreshParent = true; } @@ -758,27 +784,27 @@ if ( canEdit( 'System' ) ) { } else if ( $action == 'delete' ) { if ( !empty($_REQUEST['markIds']) ) { foreach( $_REQUEST['markIds'] as $Id ) - dbQuery( 'DELETE FROM Servers WHERE Id=?', array($Id) ); + dbQuery('DELETE FROM Servers WHERE Id=?', array($Id)); } $refreshParent = true; } else { - Error( "Unknown action $action in saving Server" ); + Error("Unknown action $action in saving Server"); } } else if ( $_REQUEST['object'] == 'storage' ) { if ( $action == 'Save' ) { if ( !empty($_REQUEST['id']) ) - $dbStorage = dbFetchOne( 'SELECT * FROM Storage WHERE Id=?', NULL, array($_REQUEST['id']) ); + $dbStorage = dbFetchOne('SELECT * FROM Storage WHERE Id=?', NULL, array($_REQUEST['id'])); else $dbStorage = array(); $types = array(); - $changes = getFormChanges( $dbStorage, $_REQUEST['newStorage'], $types ); + $changes = getFormChanges($dbStorage, $_REQUEST['newStorage'], $types); - if ( count( $changes ) ) { + if ( count($changes) ) { if ( !empty($_REQUEST['id']) ) { - dbQuery( 'UPDATE Storage SET '.implode( ', ', $changes ).' WHERE Id = ?', array($_REQUEST['id']) ); + dbQuery('UPDATE Storage SET '.implode(', ', $changes).' WHERE Id = ?', array($_REQUEST['id'])); } else { - dbQuery( 'INSERT INTO Storage set '.implode( ', ', $changes ) ); + dbQuery('INSERT INTO Storage set '.implode(', ', $changes)); } $refreshParent = true; } @@ -786,11 +812,11 @@ if ( canEdit( 'System' ) ) { } else if ( $action == 'delete' ) { if ( !empty($_REQUEST['markIds']) ) { foreach( $_REQUEST['markIds'] as $Id ) - dbQuery( 'DELETE FROM Storage WHERE Id=?', array($Id) ); + dbQuery('DELETE FROM Storage WHERE Id=?', array($Id)); } $refreshParent = true; } else { - Error( "Unknown action $action in saving Storage" ); + Error("Unknown action $action in saving Storage"); } } # end if isset($_REQUEST['object'] ) @@ -804,7 +830,7 @@ if ( canEdit( 'System' ) ) { } case 'ignore' : { - dbQuery( "update Config set Value = '".ZM_DYN_LAST_VERSION."' where Name = 'ZM_DYN_CURR_VERSION'" ); + dbQuery("UPDATE Config SET Value = '".ZM_DYN_LAST_VERSION."' WHERE Name = 'ZM_DYN_CURR_VERSION'"); break; } case 'hour' : @@ -819,12 +845,12 @@ if ( canEdit( 'System' ) ) { } elseif ( $option == 'week' ) { $nextReminder += 7*24*60*60; } - dbQuery( "update Config set Value = '".$nextReminder."' where Name = 'ZM_DYN_NEXT_REMINDER'" ); + dbQuery("UPDATE Config SET Value = '".$nextReminder."' WHERE Name = 'ZM_DYN_NEXT_REMINDER'"); break; } case 'never' : { - dbQuery( "update Config set Value = '0' where Name = 'ZM_CHECK_FOR_UPDATES'" ); + dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_CHECK_FOR_UPDATES'"); break; } } @@ -852,53 +878,51 @@ if ( canEdit( 'System' ) ) { } elseif ( $option == 'month' ) { $nextReminder += 30*24*60*60; } - dbQuery( "update Config set Value = '".$nextReminder."' where Name = 'ZM_DYN_DONATE_REMINDER_TIME'" ); + dbQuery("UPDATE Config SET Value = '".$nextReminder."' WHERE Name = 'ZM_DYN_DONATE_REMINDER_TIME'"); break; } case 'never' : case 'already' : { - dbQuery( "update Config set Value = '0' where Name = 'ZM_DYN_SHOW_DONATE_REMINDER'" ); + dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_DYN_SHOW_DONATE_REMINDER'"); break; } } // end switch option } - if ( $action == 'privacy' && isset($_REQUEST['option'] ) ) { - $option = $_REQUEST['option']; - switch( $option ) { + if ( ($action == 'privacy') && isset($_REQUEST['option']) ) { + switch( $_REQUEST['option'] ) { case 'decline' : { - dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); - dbQuery( "update Config set Value = '0' where Name = 'ZM_TELEMETRY_DATA'" ); - $view = 'console'; + dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'"); + dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_TELEMETRY_DATA'"); $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; break; } case 'accept' : { - dbQuery( "update Config set Value = '0' where Name = 'ZM_SHOW_PRIVACY'" ); - dbQuery( "update Config set Value = '1' where Name = 'ZM_TELEMETRY_DATA'" ); - $view = 'console'; + dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'"); + dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_TELEMETRY_DATA'"); $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; break; } default: # Enable the privacy statement if we somehow submit something other than accept or decline - dbQuery( "update Config set Value = '1' where Name = 'ZM_SHOW_PRIVACY'" ); + dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_SHOW_PRIVACY'"); } // end switch option + return; } if ( $action == 'options' && isset($_REQUEST['tab']) ) { $configCat = $configCats[$_REQUEST['tab']]; $changed = false; foreach ( $configCat as $name=>$value ) { - unset( $newValue ); + unset($newValue); if ( $value['Type'] == 'boolean' && empty($_REQUEST['newConfig'][$name]) ) { $newValue = 0; } else if ( isset($_REQUEST['newConfig'][$name]) ) { - $newValue = preg_replace( "/\r\n/", "\n", stripslashes( $_REQUEST['newConfig'][$name] ) ); + $newValue = preg_replace("/\r\n/", "\n", stripslashes($_REQUEST['newConfig'][$name])); } if ( isset($newValue) && ($newValue != $value['Value']) ) { - dbQuery( 'UPDATE Config SET Value=? WHERE Name=?', array( $newValue, $name ) ); + dbQuery('UPDATE Config SET Value=? WHERE Name=?', array($newValue, $name)); $changed = true; } } @@ -924,29 +948,30 @@ if ( canEdit( 'System' ) ) { } $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=options&tab='.$_REQUEST['tab']; } - loadConfig( false ); + loadConfig(false); + return; } elseif ( $action == 'user' ) { if ( !empty($_REQUEST['uid']) ) - $dbUser = dbFetchOne( "SELECT * FROM Users WHERE Id=?", NULL, array($_REQUEST['uid']) ); + $dbUser = dbFetchOne('SELECT * FROM Users WHERE Id=?', NULL, array($_REQUEST['uid'])); else $dbUser = array(); $types = array(); - $changes = getFormChanges( $dbUser, $_REQUEST['newUser'], $types ); + $changes = getFormChanges($dbUser, $_REQUEST['newUser'], $types); if ( $_REQUEST['newUser']['Password'] ) $changes['Password'] = 'Password = password('.dbEscape($_REQUEST['newUser']['Password']).')'; else - unset( $changes['Password'] ); + unset($changes['Password']); - if ( count( $changes ) ) { + if ( count($changes) ) { if ( !empty($_REQUEST['uid']) ) { - dbQuery( 'update Users set '.implode( ', ', $changes ).' where Id = ?', array($_REQUEST['uid']) ); + dbQuery('UPDATE Users SET '.implode(', ', $changes).' WHERE Id = ?', array($_REQUEST['uid'])); # If we are updating the logged in user, then update our session user data. if ( $user and ( $dbUser['Username'] == $user['Username'] ) ) - userLogin( $dbUser['Username'], $dbUser['Password'] ); + userLogin($dbUser['Username'], $dbUser['Password']); } else { - dbQuery( 'insert into Users set '.implode( ', ', $changes ) ); + dbQuery('INSERT INTO Users SET '.implode(', ', $changes)); } $refreshParent = true; } @@ -954,29 +979,28 @@ if ( canEdit( 'System' ) ) { } elseif ( $action == 'state' ) { if ( !empty($_REQUEST['runState']) ) { //if ( $cookies ) session_write_close(); - packageControl( $_REQUEST['runState'] ); + packageControl($_REQUEST['runState']); $refreshParent = true; } } elseif ( $action == 'save' ) { if ( !empty($_REQUEST['runState']) || !empty($_REQUEST['newState']) ) { $sql = 'SELECT Id,Function,Enabled FROM Monitors ORDER BY Id'; $definitions = array(); - foreach( dbFetchAll( $sql ) as $monitor ) - { + foreach( dbFetchAll($sql) as $monitor ) { $definitions[] = $monitor['Id'].':'.$monitor['Function'].':'.$monitor['Enabled']; } - $definition = join( ',', $definitions ); + $definition = join(',', $definitions); if ( $_REQUEST['newState'] ) $_REQUEST['runState'] = $_REQUEST['newState']; - dbQuery( 'replace into States set Name=?, Definition=?', array( $_REQUEST['runState'],$definition) ); + dbQuery('REPLACE INTO States SET Name=?, Definition=?', array($_REQUEST['runState'],$definition)); } } elseif ( $action == 'delete' ) { if ( isset($_REQUEST['runState']) ) - dbQuery( 'delete from States where Name=?', array($_REQUEST['runState']) ); + dbQuery('DELETE FROM States WHERE Name=?', array($_REQUEST['runState'])); if ( isset($_REQUEST['markUids']) ) { foreach( $_REQUEST['markUids'] as $markUid ) - dbQuery( 'delete from Users where Id = ?', array($markUid) ); + dbQuery('DELETE FROM Users WHERE Id = ?', array($markUid)); if ( $markUid == $user['Id'] ) userLogout(); } @@ -985,17 +1009,17 @@ if ( canEdit( 'System' ) ) { if ( ZM_USER_SELF_EDIT && $action == 'user' ) { $uid = $user['Id']; - $dbUser = dbFetchOne( 'SELECT Id, Password, Language FROM Users WHERE Id = ?', NULL, array($uid) ); + $dbUser = dbFetchOne('SELECT Id, Password, Language FROM Users WHERE Id = ?', NULL, array($uid)); $types = array(); - $changes = getFormChanges( $dbUser, $_REQUEST['newUser'], $types ); + $changes = getFormChanges($dbUser, $_REQUEST['newUser'], $types); if ( !empty($_REQUEST['newUser']['Password']) ) $changes['Password'] = 'Password = password('.dbEscape($_REQUEST['newUser']['Password']).')'; else - unset( $changes['Password'] ); - if ( count( $changes ) ) { - dbQuery( 'update Users set '.implode( ', ', $changes ).' where Id=?', array($uid) ); + unset($changes['Password']); + if ( count($changes) ) { + dbQuery('UPDATE Users SET '.implode(', ', $changes).' WHERE Id=?', array($uid)); $refreshParent = true; } $view = 'none'; @@ -1004,8 +1028,8 @@ if ( canEdit( 'System' ) ) { if ( $action == 'reset' ) { session_start(); - $_SESSION['zmEventResetTime'] = strftime( STRF_FMT_DATETIME_DB ); - setcookie( 'zmEventResetTime', $_SESSION['zmEventResetTime'], time()+3600*24*30*12*10 ); + $_SESSION['zmEventResetTime'] = strftime(STRF_FMT_DATETIME_DB); + setcookie('zmEventResetTime', $_SESSION['zmEventResetTime'], time()+3600*24*30*12*10); session_write_close(); } From 0823b287128092ffcbed0a6661ec085c2b752ca5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 10:37:11 -0400 Subject: [PATCH 38/52] whitespace changes. Make Privacy test an else so that PRIVACY checks don't happen if not logged in --- web/index.php | 120 ++++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/web/index.php b/web/index.php index 69745ce3c..9df89ac4b 100644 --- a/web/index.php +++ b/web/index.php @@ -18,17 +18,17 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -error_reporting( E_ALL ); +error_reporting(E_ALL); $debug = false; if ( $debug ) { // Use these for debugging, though not both at once! - phpinfo( INFO_VARIABLES ); + phpinfo(INFO_VARIABLES); //error_reporting( E_ALL ); } // Use new style autoglobals where possible -if ( version_compare( phpversion(), '4.1.0', '<') ) { +if ( version_compare(phpversion(), '4.1.0', '<') ) { $_SESSION = &$HTTP_SESSION_VARS; $_SERVER = &$HTTP_SERVER_VARS; } @@ -36,20 +36,20 @@ if ( version_compare( phpversion(), '4.1.0', '<') ) { // Useful debugging lines for mobile devices if ( false ) { ob_start(); - phpinfo( INFO_VARIABLES ); - $fp = fopen( '/tmp/env.html', 'w' ); - fwrite( $fp, ob_get_contents() ); - fclose( $fp ); + phpinfo(INFO_VARIABLES); + $fp = fopen('/tmp/env.html', 'w'); + fwrite($fp, ob_get_contents()); + fclose($fp); ob_end_clean(); } -require_once( 'includes/config.php' ); -require_once( 'includes/logger.php' ); -require_once( 'includes/Server.php' ); -require_once( 'includes/Storage.php' ); -require_once( 'includes/Event.php' ); -require_once( 'includes/Group.php' ); -require_once( 'includes/Monitor.php' ); +require_once('includes/config.php'); +require_once('includes/logger.php'); +require_once('includes/Server.php'); +require_once('includes/Storage.php'); +require_once('includes/Event.php'); +require_once('includes/Group.php'); +require_once('includes/Monitor.php'); if ( @@ -61,13 +61,13 @@ if ( } else { $protocol = 'http'; } -define( 'ZM_BASE_PROTOCOL', $protocol ); +define('ZM_BASE_PROTOCOL', $protocol); // Absolute URL's are unnecessary and break compatibility with reverse proxies // define( "ZM_BASE_URL", $protocol.'://'.$_SERVER['HTTP_HOST'] ); // Use relative URL's instead -define( 'ZM_BASE_URL', '' ); +define('ZM_BASE_URL', ''); // Check time zone is set if (!ini_get('date.timezone') || !date_default_timezone_set(ini_get('date.timezone'))) { @@ -85,10 +85,10 @@ if ( isset($_GET['skin']) ) { $skin = 'classic'; } -$skins = array_map( 'basename', glob('skins/*', GLOB_ONLYDIR ) ); +$skins = array_map('basename', glob('skins/*', GLOB_ONLYDIR)); -if ( ! in_array( $skin, $skins ) ) { - Error( "Invalid skin '$skin' setting to " . $skins[0] ); +if ( ! in_array($skin, $skins) ) { + Error("Invalid skin '$skin' setting to " . $skins[0]); $skin = $skins[0]; } @@ -96,25 +96,25 @@ if ( isset($_GET['css']) ) { $css = $_GET['css']; } elseif ( isset($_COOKIE['zmCSS']) ) { $css = $_COOKIE['zmCSS']; -} elseif (defined('ZM_CSS_DEFAULT')) { +} elseif ( defined('ZM_CSS_DEFAULT') ) { $css = ZM_CSS_DEFAULT; } else { $css = 'classic'; } -$css_skins = array_map( 'basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR) ); -if ( ! in_array( $css, $css_skins ) ) { - Error( "Invalid skin css '$css' setting to " . $css_skins[0] ); +$css_skins = array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)); +if ( !in_array($css, $css_skins) ) { + Error("Invalid skin css '$css' setting to " . $css_skins[0]); $css = $css_skins[0]; } -define( 'ZM_BASE_PATH', dirname( $_SERVER['REQUEST_URI'] ) ); -define( 'ZM_SKIN_PATH', "skins/$skin" ); -define( 'ZM_SKIN_NAME', $skin ); +define('ZM_BASE_PATH', dirname($_SERVER['REQUEST_URI'])); +define('ZM_SKIN_PATH', "skins/$skin"); +define('ZM_SKIN_NAME', $skin); $skinBase = array(); // To allow for inheritance of skins -if ( !file_exists( ZM_SKIN_PATH ) ) - Fatal( "Invalid skin '$skin'" ); +if ( !file_exists(ZM_SKIN_PATH) ) + Fatal("Invalid skin '$skin'"); $skinBase[] = $skin; $currentCookieParams = session_get_cookie_params(); @@ -127,25 +127,25 @@ session_set_cookie_params( true ); -ini_set( 'session.name', 'ZMSESSID' ); +ini_set('session.name', 'ZMSESSID'); session_start(); if ( !isset($_SESSION['skin']) || isset($_REQUEST['skin']) || !isset($_COOKIE['zmSkin']) || $_COOKIE['zmSkin'] != $skin ) { $_SESSION['skin'] = $skin; - setcookie( 'zmSkin', $skin, time()+3600*24*30*12*10 ); + setcookie('zmSkin', $skin, time()+3600*24*30*12*10); } if ( !isset($_SESSION['css']) || isset($_REQUEST['css']) || !isset($_COOKIE['zmCSS']) || $_COOKIE['zmCSS'] != $css ) { $_SESSION['css'] = $css; - setcookie( 'zmCSS', $css, time()+3600*24*30*12*10 ); + setcookie('zmCSS', $css, time()+3600*24*30*12*10); } if ( ZM_OPT_USE_AUTH ) { - if ( isset( $_SESSION['user'] ) ) { + if ( isset($_SESSION['user']) ) { $user = $_SESSION['user']; } else { - unset( $user ); + unset($user); } } else { $user = $defaultUser; @@ -154,9 +154,9 @@ if ( ZM_OPT_USE_AUTH ) { # Any file/page that sets session variables must re-open it. session_write_close(); -require_once( 'includes/lang.php' ); -require_once( 'includes/functions.php' ); -require_once( 'includes/auth.php' ); +require_once('includes/lang.php'); +require_once('includes/functions.php'); +require_once('includes/auth.php'); # Running is global but only do the daemonCheck if it is actually needed $running = null; @@ -179,20 +179,20 @@ $request = null; if ( isset($_REQUEST['request']) ) $request = detaintPath($_REQUEST['request']); -foreach ( getSkinIncludes( 'skin.php' ) as $includeFile ) +foreach ( getSkinIncludes('skin.php') as $includeFile ) require_once $includeFile; if ( ZM_OPT_USE_AUTH ) { if ( ZM_AUTH_HASH_LOGINS ) { if ( empty($user) && ! empty($_REQUEST['auth']) ) { - if ( $authUser = getAuthUser( $_REQUEST['auth'] ) ) { - userLogin( $authUser['Username'], $authUser['Password'], true ); + if ( $authUser = getAuthUser($_REQUEST['auth']) ) { + userLogin($authUser['Username'], $authUser['Password'], true); } } } - if ( ! empty($user) ) { + if ( !empty($user) ) { // generate it once here, while session is open. Value will be cached in session and return when called later on - generateAuthHash( ZM_AUTH_HASH_IPS ); + generateAuthHash(ZM_AUTH_HASH_IPS); } } @@ -205,24 +205,30 @@ isset($view) || $view = NULL; isset($request) || $request = NULL; isset($action) || $action = NULL; -if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $request != 'control' && $view != 'frames' && $view != 'archive' ) { +Logger::Debug("View: $view Request: $request Action: $action"); +if ( + ZM_ENABLE_CSRF_MAGIC && + ( $action != 'login' ) && + ( $view != 'view_video' ) && + ( $request != 'control' ) && + ( $view != 'frames' ) && + ( $view != 'archive' ) +) { require_once( 'includes/csrf/csrf-magic.php' ); #Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); csrf_check(); } # Need to include actions because it does auth -require_once( 'includes/actions.php' ); +require_once('includes/actions.php'); # If I put this here, it protects all views and popups, but it has to go after actions.php because actions.php does the actual logging in. -if ( ZM_OPT_USE_AUTH and ! isset($user) ) { - Logger::Debug("Redirecting to login" ); +if ( ZM_OPT_USE_AUTH and !isset($user) ) { + Logger::Debug('Redirecting to login'); $view = 'login'; $request = null; -} - -if ( ZM_SHOW_PRIVACY && canEdit('System') ) { - Logger::Debug("Redirecting to privacy" ); +} else if ( ZM_SHOW_PRIVACY && ($action != 'privacy') && ($view !='options') && (!$request) && canEdit('System') ) { + Logger::Debug('Redirecting to privacy'); $view = 'privacy'; $request = null; } @@ -233,17 +239,17 @@ if ( $redirect ) { } if ( $request ) { - foreach ( getSkinIncludes( 'ajax/'.$request.'.php', true, true ) as $includeFile ) { - if ( !file_exists( $includeFile ) ) - Fatal( "Request '$request' does not exist" ); + foreach ( getSkinIncludes('ajax/'.$request.'.php', true, true) as $includeFile ) { + if ( !file_exists($includeFile) ) + Fatal("Request '$request' does not exist"); require_once $includeFile; } return; } else { - if ( $includeFiles = getSkinIncludes( 'views/'.$view.'.php', true, true ) ) { + if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) { foreach ( $includeFiles as $includeFile ) { - if ( !file_exists( $includeFile ) ) - Fatal( "View '$view' does not exist" ); + if ( !file_exists($includeFile) ) + Fatal("View '$view' does not exist"); require_once $includeFile; } // If the view overrides $view to 'error', and the user is not logged in, then the @@ -251,14 +257,14 @@ if ( $request ) { // The login view should handle redirecting to the correct location afterward. if ( $view == 'error' && !isset($user) ) { $view = 'login'; - foreach ( getSkinIncludes( 'views/login.php', true, true ) as $includeFile ) + foreach ( getSkinIncludes('views/login.php', true, true) as $includeFile ) require_once $includeFile; } } // If the view is missing or the view still returned error with the user logged in, // then it is not recoverable. if ( !$includeFiles || $view == 'error' ) { - foreach ( getSkinIncludes( 'views/error.php', true, true ) as $includeFile ) + foreach ( getSkinIncludes('views/error.php', true, true) as $includeFile ) require_once $includeFile; } } From 57d5e28870fa98735b602855324aac8a22ab844e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 11:57:47 -0400 Subject: [PATCH 39/52] clear output buffer before sending image. Adjust filename for saveAs when doing a scaled image. whitespace corrections. More Debug output --- web/views/image.php | 78 +++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/web/views/image.php b/web/views/image.php index 26c58f4f7..552b81256 100644 --- a/web/views/image.php +++ b/web/views/image.php @@ -40,7 +40,7 @@ require_once('includes/Event.php'); require_once('includes/Frame.php'); // Compatibility for PHP 5.4 -if (!function_exists('imagescale')) { +if ( !function_exists('imagescale') ) { function imagescale($image, $new_width, $new_height = -1, $mode = 0) { $mode; // Not supported @@ -70,17 +70,18 @@ if ( empty($_REQUEST['path']) ) { if ( !empty($_REQUEST['eid']) ) { $Event = Event::find_one(array('Id'=>$_REQUEST['eid'])); - if ( ! $Event ) { + if ( !$Event ) { header('HTTP/1.0 404 Not Found'); - Fatal('Event ' . $_REQUEST['eid'].' Not found'); + Fatal('Event '.$_REQUEST['eid'].' Not found'); return; } if ( $_REQUEST['fid'] == 'snapshot' ) { $Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'Score'=>$Event->MaxScore())); - if ( ! $Frame ) + if ( !$Frame ) $Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'])); - if ( ! $Frame ) { + if ( !$Frame ) { + Warning("No frame found for event " + $_REQUEST['eid']); $Frame = new Frame(); $Frame->Delta(1); $Frame->FrameId('snapshot'); @@ -123,14 +124,14 @@ Logger::Debug("Got virtual frame from Bulk Frames previous delta: " . $previousB } else { # If we are only specifying fid, then the fid must be the primary key into the frames table. But when the event is specified, then it is the frame # $Frame = Frame::find_one(array('Id'=>$_REQUEST['fid'])); - if ( ! $Frame ) { + if ( !$Frame ) { header('HTTP/1.0 404 Not Found'); Fatal('Frame ' . $_REQUEST['fid'] . ' Not Found'); return; } $Event = Event::find_one(array('Id'=>$Frame->EventId())); - if ( ! $Event ) { + if ( !$Event ) { header('HTTP/1.0 404 Not Found'); Fatal('Event ' . $Frame->EventId() . ' Not Found'); return; @@ -138,11 +139,11 @@ Logger::Debug("Got virtual frame from Bulk Frames previous delta: " . $previousB $path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg'; } # end if have eid - if ( ! file_exists($path) ) { + if ( !file_exists($path) ) { Logger::Debug("$path does not exist"); # Generate the frame JPG - if ( $show == 'capture' and $Event->DefaultVideo() ) { - if ( ! file_exists($Event->Path().'/'.$Event->DefaultVideo()) ) { + if ( ($show == 'capture') and $Event->DefaultVideo() ) { + if ( !file_exists($Event->Path().'/'.$Event->DefaultVideo()) ) { header('HTTP/1.0 404 Not Found'); Fatal("Can't create frame images from video because there is no video file for this event at (".$Event->Path().'/'.$Event->DefaultVideo() ); } @@ -190,52 +191,52 @@ Logger::Debug("Got virtual frame from Bulk Frames previous delta: " . $previousB } else { $errorText = 'Invalid image path'; } - if ( ! file_exists($path) ) { + if ( !file_exists($path) ) { header('HTTP/1.0 404 Not Found'); Fatal("Image not found at $path"); } } -$scale=0; +$scale = 0; if ( !empty($_REQUEST['scale']) ) { if ( is_numeric($_REQUEST['scale']) ) { $x = $_REQUEST['scale']; if ( $x >= 1 and $x <= 400 ) - $scale=$x; + $scale = $x; } } -$width=0; +$width = 0; if ( !empty($_REQUEST['width']) ) { if ( is_numeric($_REQUEST['width']) ) { $x = $_REQUEST['width']; if ( $x >= 10 and $x <= 8000 ) - $width=$x; + $width = $x; } } -$height=0; +$height = 0; if ( !empty($_REQUEST['height']) ) { if ( is_numeric($_REQUEST['height']) ) { $x = $_REQUEST['height']; if ( $x >= 10 and $x <= 8000 ) - $height=$x; + $height = $x; } } -header('Content-type: image/jpeg'); - -# This is so that Save Image As give a useful filename -if ( $Event ) { - $filename = $Event->MonitorId().'_'.$Event->Id().'_'.$Frame->FrameId().'.jpg'; - header('Content-Disposition: inline; filename="' . $filename . '"'); -} -ob_clean(); -flush(); - if ( $errorText ) { Error($errorText); } else { + # Clears the output buffer. Not sure what is there, but have had troubles. + ob_end_clean(); + header('Content-type: image/jpeg'); if ( ( $scale==0 || $scale==100 ) && $width==0 && $height==0 ) { + # This is so that Save Image As give a useful filename + if ( $Event ) { + $filename = $Event->MonitorId().'_'.$Event->Id().'_'.$Frame->FrameId().'.jpg'; + header('Content-Disposition: inline; filename="' . $filename . '"'); + } + ob_clean(); + flush(); if ( !readfile($path) ) { Error('No bytes read from '. $path); } @@ -254,17 +255,23 @@ if ( $errorText ) { } elseif ( $width != 0 && $height == 0 ) { $height = ($width * $oldHeight) / $oldWidth; } - if ( $width == $oldWidth && $height == $oldHeight) { + if ( $width == $oldWidth && $height == $oldHeight ) { Warning('No change to width despite scaling.'); } } # Slight optimisation, thumbnails always specify width and height, so we can cache them. - $scaled_path = preg_replace('/\.jpg$/', "-${width}x${height}.jpg", $path ); - if ( ! file_exists($scaled_path) or ! readfile($scaled_path) ) { + $scaled_path = preg_replace('/\.jpg$/', "-${width}x${height}.jpg", $path); + if ( $Event ) { + $filename = $Event->MonitorId().'_'.$Event->Id().'_'.$Frame->FrameId()."-${width}x${height}.jpg"; + header('Content-Disposition: inline; filename="' . $filename . '"'); + } + //ob_clean(); + //flush(); + if ( !( file_exists($scaled_path) and readfile($scaled_path) ) ) { Logger::Debug("Cached scaled image does not exist at $scaled_path or is no good.. Creating it"); ob_start(); - if ( ! $i ) + if ( !$i ) $i = imagecreatefromjpeg($path); $iScale = imagescale($i, $width, $height); imagejpeg($iScale); @@ -274,6 +281,15 @@ if ( $errorText ) { file_put_contents($scaled_path, $scaled_jpeg_data); ob_end_clean(); echo $scaled_jpeg_data; + } else { + Logger::Debug("Sending $scaled_path"); + $bytes = readfile($scaled_path); + if ( !$bytes ) { + Error('No bytes read from '. $scaled_path); + } else { + Logger::Debug("$bytes sent"); + } } } } +exit(); From 7ee80e7ccadd461df6cc2d0cf607347cd4882dc1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 11:58:03 -0400 Subject: [PATCH 40/52] Debug lines should be debug, not warning --- web/includes/database.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/includes/database.php b/web/includes/database.php index 2c3a818c1..55535659f 100644 --- a/web/includes/database.php +++ b/web/includes/database.php @@ -139,9 +139,9 @@ function dbQuery( $sql, $params=NULL ) { } if ( defined('ZM_DB_DEBUG') ) { if ( $params ) - Warning("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() ); + Logger::Debug("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() ); else - Warning("SQL: $sql: rows:" . $result->rowCount() ); + Logger::Debug("SQL: $sql: rows:" . $result->rowCount() ); } } catch(PDOException $e) { Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') ); From 623d31edae25c23eb8df5aee9bf5eda4e66e30a3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 11:58:17 -0400 Subject: [PATCH 41/52] Don't do csrf for view=image --- web/index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/index.php b/web/index.php index 9df89ac4b..0bda75ad6 100644 --- a/web/index.php +++ b/web/index.php @@ -210,6 +210,7 @@ if ( ZM_ENABLE_CSRF_MAGIC && ( $action != 'login' ) && ( $view != 'view_video' ) && + ( $view != 'image' ) && ( $request != 'control' ) && ( $view != 'frames' ) && ( $view != 'archive' ) From 798aab84f3695049828ff566706d2ba6ff2252eb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 11:58:33 -0400 Subject: [PATCH 42/52] whitespace changes --- web/views/view_video.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/web/views/view_video.php b/web/views/view_video.php index cb5707139..9bba64e69 100644 --- a/web/views/view_video.php +++ b/web/views/view_video.php @@ -25,7 +25,7 @@ // Does not support scaling at this time. // -if ( !canView( 'Events' ) ) { +if ( !canView('Events') ) { $view = 'error'; return; } @@ -37,12 +37,12 @@ $path = ''; $Event = null; -if ( ! empty($_REQUEST['eid'] ) ) { - $Event = new Event( $_REQUEST['eid'] ); +if ( ! empty($_REQUEST['eid']) ) { + $Event = new Event($_REQUEST['eid']); $path = $Event->Path().'/'.$Event->DefaultVideo(); Logger::Debug("Path: $path"); -} else if ( ! empty($_REQUEST['event_id'] ) ) { - $Event = new Event( $_REQUEST['event_id'] ); +} else if ( ! empty($_REQUEST['event_id']) ) { + $Event = new Event($_REQUEST['event_id']); $path = $Event->Path().'/'.$Event->DefaultVideo(); Logger::Debug("Path: $path"); } else { @@ -50,7 +50,7 @@ if ( ! empty($_REQUEST['eid'] ) ) { } if ( $errorText ) { - Error( $errorText ); + Error($errorText); header('HTTP/1.0 404 Not Found'); die(); } @@ -67,12 +67,12 @@ $begin = 0; $end = $size-1; $length = $size; -if ( isset( $_SERVER['HTTP_RANGE'] ) ) { - Logger::Debug("Using Range " . $_SERVER['HTTP_RANGE'] ); - if ( preg_match( '/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches) ) { - $begin = intval( $matches[1] ); - if ( ! empty( $matches[2]) ) { - $end = intval( $matches[2] ); +if ( isset($_SERVER['HTTP_RANGE']) ) { + Logger::Debug('Using Range ' . $_SERVER['HTTP_RANGE']); + if ( preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches) ) { + $begin = intval($matches[1]); + if ( ! empty($matches[2]) ) { + $end = intval($matches[2]); } $length = $end - $begin + 1; Logger::Debug("Using Range $begin $end size: $size, length: $length"); @@ -102,10 +102,10 @@ ob_clean(); flush(); $cur = $begin; -fseek( $fh, $begin, 0 ); +fseek($fh, $begin, 0); -while( $length && ( ! feof( $fh ) ) && ( connection_status() == 0 ) ) { - $amount = min( 1024*16, $length ); +while( $length && ( !feof($fh) ) && ( connection_status() == 0 ) ) { + $amount = min(1024*16, $length); print fread( $fh, $amount ); $length -= $amount; @@ -114,5 +114,5 @@ while( $length && ( ! feof( $fh ) ) && ( connection_status() == 0 ) ) { flush(); } -fclose( $fh ); +fclose($fh); exit(); From 9ec415b30a0d996381c61b76b828342e651a0196 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 31 Aug 2018 15:56:21 -0400 Subject: [PATCH 43/52] Just reload the event view instead of dynamically updating the stream. Fixes #2196 --- web/skins/classic/views/js/event.js | 89 ++++++++++++++++++----------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 9d963c745..86989cbf6 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -180,7 +180,7 @@ function changeScale() { function changeReplayMode() { var replayMode = $('replayMode').get('value'); - Cookie.write( 'replayMode', replayMode, { duration: 10*365 }); + Cookie.write('replayMode', replayMode, { duration: 10*365 }); refreshWindow(); } @@ -195,6 +195,8 @@ var zmsBroke = false; //Use alternate navigation if zms has crashed function getCmdResponse( respObj, respText ) { if ( checkStreamForErrors( "getCmdResponse", respObj ) ) { console.log('Got an error from getCmdResponse'); + console.log(respObj); + console.log(respText); zmsBroke = true; return; } @@ -202,18 +204,24 @@ function getCmdResponse( respObj, respText ) { zmsBroke = false; if ( streamCmdTimer ) - streamCmdTimer = clearTimeout( streamCmdTimer ); + streamCmdTimer = clearTimeout(streamCmdTimer); streamStatus = respObj.status; - if (streamStatus.progress >= Math.round(parseFloat(eventData.Length))) streamStatus.progress = parseFloat(eventData.Length); //Limit progress to reality + if ( streamStatus.progress >= Math.round(parseFloat(eventData.Length)) ) + streamStatus.progress = parseFloat(eventData.Length); //Limit progress to reality var eventId = streamStatus.event; - if ( eventId != lastEventId && lastEventId != 0) { //Doesn't run on first load, prevents a double hit on event and nearEvents ajax - eventQuery( eventId ); - initialAlarmCues(eventId); //zms uses this instead of a page reload, must call ajax+render - lastEventId = eventId; + if ( lastEventId ) { + if ( eventId != lastEventId ) { + //Doesn't run on first load, prevents a double hit on event and nearEvents ajax + eventQuery(eventId); + initialAlarmCues(eventId); //zms uses this instead of a page reload, must call ajax+render + lastEventId = eventId; + } + } else { + lastEventId = eventId; //Only fires on first load. } - if (lastEventId == 0) lastEventId = eventId; //Only fires on first load. + if ( streamStatus.paused == true ) { streamPause( ); } else { @@ -239,18 +247,24 @@ function getCmdResponse( respObj, respText ) { streamCmdTimer = streamQuery.delay( streamTimeout ); //Timeout is refresh rate for progressBox and time display } -var streamReq = new Request.JSON( { url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getCmdResponse } ); +var streamReq = new Request.JSON( { + url: thisUrl, + method: 'get', + timeout: AJAX_TIMEOUT, + link: 'chain', + onSuccess: getCmdResponse +} ); function pauseClicked() { - if (vid) { + if ( vid ) { vid.pause(); } else { - streamReq.send( streamParms+"&command="+CMD_PAUSE ); + streamReq.send(streamParms+"&command="+CMD_PAUSE); streamPause(); } } -function vjsPause () { +function vjsPause() { stopFastRev(); streamPause(); } @@ -267,8 +281,8 @@ function streamPause( ) { } function playClicked( ) { - if (vid) { - if (vid.paused()) { + if ( vid ) { + if ( vid.paused() ) { vid.play(); } else { vjsPlay(); //handles fast forward and rewind @@ -279,7 +293,7 @@ function playClicked( ) { } } -function vjsPlay () { //catches if we change mode programatically +function vjsPlay() { //catches if we change mode programatically stopFastRev(); $j('#rateValue').html(vid.playbackRate()); streamPlay(); @@ -302,13 +316,14 @@ function streamFastFwd( action ) { setButtonState( $('slowFwdBtn'), 'unavail' ); setButtonState( $('slowRevBtn'), 'unavail' ); setButtonState( $('fastRevBtn'), 'inactive' ); - if (vid) { - if (revSpeed != .5) stopFastRev(); + if ( vid ) { + if ( revSpeed != .5 ) stopFastRev(); vid.playbackRate(rates[rates.indexOf(vid.playbackRate()*100)-1]/100); - if (rates.indexOf(vid.playbackRate()*100)-1 == -1) setButtonState($('fastFwdBtn'), 'unavail'); + if ( rates.indexOf(vid.playbackRate()*100)-1 == -1 ) + setButtonState($('fastFwdBtn'), 'unavail'); $j('#rateValue').html(vid.playbackRate()); } else { - streamReq.send( streamParms+"&command="+CMD_FASTFWD ); + streamReq.send(streamParms+"&command="+CMD_FASTFWD); } } @@ -317,22 +332,22 @@ var intervalRewind; var revSpeed = .5; function streamSlowFwd( action ) { - if (vid) { + if ( vid ) { vid.currentTime(vid.currentTime() + spf); } else { - streamReq.send( streamParms+"&command="+CMD_SLOWFWD ); + streamReq.send(streamParms+"&command="+CMD_SLOWFWD); } } function streamSlowRev( action ) { - if (vid) { + if ( vid ) { vid.currentTime(vid.currentTime() - spf); } else { - streamReq.send( streamParms+"&command="+CMD_SLOWREV ); + streamReq.send(streamParms+"&command="+CMD_SLOWREV); } } -function stopFastRev () { +function stopFastRev() { clearInterval(intervalRewind); vid.playbackRate(1); revSpeed = .5; @@ -345,9 +360,9 @@ function streamFastRev( action ) { setButtonState( $('slowFwdBtn'), 'unavail' ); setButtonState( $('slowRevBtn'), 'unavail' ); setButtonState( $('fastRevBtn'), 'active' ); - if (vid) { //There is no reverse play with mp4. Set the speed to 0 and manualy set the time back. + if ( vid ) { //There is no reverse play with mp4. Set the speed to 0 and manualy set the time back. revSpeed = rates[rates.indexOf(revSpeed*100)-1]/100; - if (rates.indexOf(revSpeed*100) == 0) { + if ( rates.indexOf(revSpeed*100) == 0 ) { setButtonState( $('fastRevBtn'), 'unavail' ); } clearInterval(intervalRewind); @@ -367,9 +382,12 @@ function streamFastRev( action ) { } function streamPrev(action) { - if (action) { + if ( action ) { $j(".vjsMessage").remove(); - if (vid && PrevEventDefVideoPath.indexOf("view_video") > 0) { + location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery); + return; + + if ( vid && PrevEventDefVideoPath.indexOf("view_video") > 0 ) { CurEventDefVideoPath = PrevEventDefVideoPath; eventQuery(prevEventId); } else if (zmsBroke || (vid && PrevEventDefVideoPath.indexOf("view_video") < 0) || $j("#vjsMessage").length || PrevEventDefVideoPath.indexOf("view_video") > 0) {//zms broke, leaving videojs, last event, moving to videojs @@ -382,20 +400,25 @@ function streamPrev(action) { } function streamNext(action) { - if (action) { + if ( action ) { $j(".vjsMessage").remove();//This shouldn't happen - if (nextEventId == 0) { //handles deleting last event. + if ( nextEventId == 0 ) { //handles deleting last event. pauseClicked(); let hideContainer = $j('#eventVideo'); let hideStream = $j(vid ? "#videoobj" : "#evtStream").height() + (vid ? 0 :$j("#progressBar").height()); hideContainer.prepend('

No more events

'); - if (vid == null) zmsBroke = true; + if ( vid == null ) zmsBroke = true; return; } - if (vid && NextEventDefVideoPath.indexOf("view_video") > 0) { //on and staying with videojs + // We used to try to dynamically update all the bits in the page, which is really complex + // How about we just reload the page? + // + location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery); + return; + if ( vid && ( NextEventDefVideoPath.indexOf("view_video") > 0 ) ) { //on and staying with videojs CurEventDefVideoPath = NextEventDefVideoPath; eventQuery(nextEventId); - } else if (zmsBroke || (vid && NextEventDefVideoPath.indexOf("view_video") < 0) || NextEventDefVideoPath.indexOf("view_video") > 0) {//reload zms, leaving vjs, moving to vjs + } else if ( zmsBroke || (vid && NextEventDefVideoPath.indexOf("view_video") < 0) || NextEventDefVideoPath.indexOf("view_video") > 0) {//reload zms, leaving vjs, moving to vjs location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery); } else { streamReq.send(streamParms+"&command="+CMD_NEXT); From 563e673bee74053a39557a991b37e6079ffff423 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 1 Sep 2018 11:53:56 -0500 Subject: [PATCH 44/52] rpm - rename README.xxx to README for all builds --- distros/redhat/CMakeLists.txt | 9 +++++++-- distros/redhat/zoneminder.spec | 6 ++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index 683a475b1..d940942c1 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -1,4 +1,4 @@ -# CMakeLists.txt for the Redhat/CentOS Target Distro. +# CMakeLists.txt for the Redhat Target Distros. # Display a message to show the RHEL build options are being processed. if(ZM_TARGET_DISTRO MATCHES "^el") @@ -20,11 +20,16 @@ if(ZM_WEB_USER STREQUAL "nginx") configure_file(nginx/zoneminder.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.conf @ONLY) configure_file(nginx/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY) configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) - configure_file(nginx/README.Fedora ${CMAKE_CURRENT_SOURCE_DIR}/readme/README.Fedora COPYONLY) + configure_file(nginx/README.Fedora ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) else(ZM_WEB_USER STREQUAL "nginx") configure_file(systemd/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) configure_file(apache/zoneminder.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.conf @ONLY) configure_file(systemd/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY) + if( ZM_TARGET_DISTRO MATCHES "^fc") + configure_file(readme/README.Fedora ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) + else( ZM_TARGET_DISTRO MATCHES "^fc") + configure_file(readme/README.Redhat7 ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) + endif( ZM_TARGET_DISTRO MATCHES "^fc") endif(ZM_WEB_USER STREQUAL "nginx") # Create several empty folders diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index a91a3a78e..d619f3662 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -22,7 +22,6 @@ %global with_apcu_bc 1 %endif -%global readme_suffix %{?rhel:Redhat%{?rhel}}%{!?rhel:Fedora} %global _hardened_build 1 Name: zoneminder @@ -203,8 +202,7 @@ fi %{_bindir}/gpasswd -a %{zmuid_final} dialout >/dev/null 2>&1 || : # Warn the end user to read the README file -echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, read README.%{readme_suffix} to finish the\ninstallation or upgrade!\n" -echo -e "\nThe README file is located here: %{_docdir}/%{name}\n" +echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, read %{_docdir}/README\nto finish the installation or upgrade!\n" %if 0%{?with_nginx} # Nginx does not create an SSL certificate like the apache package does so lets do that here @@ -252,7 +250,7 @@ EOF %files %license COPYING -%doc AUTHORS README.md distros/redhat/readme/README.%{readme_suffix} distros/redhat/readme/README.https +%doc AUTHORS README.md distros/redhat/README distros/redhat/readme/README.https # We want these two folders to have "normal" read permission # compared to the folder contents From 86f043633a87fa9ff188ec186450d892af365d85 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 1 Sep 2018 12:04:48 -0500 Subject: [PATCH 45/52] typo --- distros/redhat/zoneminder.spec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index d619f3662..ba6945966 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -202,7 +202,8 @@ fi %{_bindir}/gpasswd -a %{zmuid_final} dialout >/dev/null 2>&1 || : # Warn the end user to read the README file -echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, read %{_docdir}/README\nto finish the installation or upgrade!\n" +echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README file\nto finish the installation or upgrade!\n" +echo -e "\nThe README file is located here: %{_docdir}/README\n" %if 0%{?with_nginx} # Nginx does not create an SSL certificate like the apache package does so lets do that here @@ -250,7 +251,7 @@ EOF %files %license COPYING -%doc AUTHORS README.md distros/redhat/README distros/redhat/readme/README.https +%doc AUTHORS README.md distros/redhat/readme/README distros/redhat/readme/README.https # We want these two folders to have "normal" read permission # compared to the folder contents From 36322f91295c9ec1c5171968f9ed33ad41abf481 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 1 Sep 2018 12:15:08 -0500 Subject: [PATCH 46/52] rpm - use _pkgdocdir instead of _docdir --- distros/redhat/zoneminder.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index ba6945966..8ed07898d 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -202,8 +202,8 @@ fi %{_bindir}/gpasswd -a %{zmuid_final} dialout >/dev/null 2>&1 || : # Warn the end user to read the README file -echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README file\nto finish the installation or upgrade!\n" -echo -e "\nThe README file is located here: %{_docdir}/README\n" +echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README file\nto finish the installation or upgrade!" +echo -e "\nThe README file is located here: %{_pkgdocdir}/README\n" %if 0%{?with_nginx} # Nginx does not create an SSL certificate like the apache package does so lets do that here From e5a2581dcce33f73ba2be54e4728fea4334f0cae Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 3 Sep 2018 08:56:52 -0500 Subject: [PATCH 47/52] optionhelp - support links markdown style (#2198) --- web/skins/classic/views/optionhelp.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/optionhelp.php b/web/skins/classic/views/optionhelp.php index 705c5101f..fe466ea62 100644 --- a/web/skins/classic/views/optionhelp.php +++ b/web/skins/classic/views/optionhelp.php @@ -22,6 +22,7 @@ $optionHelpIndex = preg_replace( '/^ZM_/', '', $_REQUEST['option'] ); $optionHelpText = !empty($OLANG[$optionHelpIndex])?$OLANG[$optionHelpIndex]['Help']:$config[$_REQUEST['option']]['Help']; $optionHelpText = validHtmlStr($optionHelpText); $optionHelpText = preg_replace( "/~~/", "
", $optionHelpText ); +$optionHelpText = preg_replace( "/\[(.+)\]\((.+)\)/", "$1", $optionHelpText ); $focusWindow = true; From ce48343d1a82efe3097e267a1d81288cc5af208c Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Mon, 3 Sep 2018 13:55:11 -0500 Subject: [PATCH 48/52] embed link to privacy statment in telemetry help text --- 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 6a3a66dae..319ac4489 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -2721,7 +2721,8 @@ our @options = ( This is being done for the sole purpoase of creating a better product for our target audience. This script is intended to be completely transparent to the end user, and can be disabled from - the web console under Options. + the web console under Options. For more details on what information + we collect, please refer to our [privacy](?view=privacy) statement. `, type => $types{boolean}, category => 'system', From 13558b2c125b9d3592bb1cbbff9338bfd2e455e1 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 4 Sep 2018 07:39:46 -0500 Subject: [PATCH 49/52] convert existing http urls in help text to markdown --- .../lib/ZoneMinder/ConfigData.pm.in | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 319ac4489..eac13cb75 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -409,8 +409,8 @@ our @options = ( that is used to get notifications for alarms detected by ZoneMinder in real time. zmNinja requires this server for push notifications to mobile phones. This option only enables the server if its already installed. - Please visit https://github.com/pliablepixels/zmeventserver for installation - instructions. + Please visit the [zmeventserver project site](https://github.com/pliablepixels/zmeventserver) + for installation instructions. `, type => $types{boolean}, category => 'system', @@ -442,7 +442,7 @@ our @options = ( description => 'Your recaptcha site-key', help => q`You need to generate your keys from the Google reCaptcha website. - Please refer to https://www.google.com/recaptcha/ + Please refer to the [recaptcha project site](https://www.google.com/recaptcha/) for more details. `, requires => [ @@ -457,7 +457,7 @@ our @options = ( description => 'Your recaptcha secret-key', help => q`You need to generate your keys from the Google reCaptcha website. - Please refer to https://www.google.com/recaptcha/ + Please refer to the [recaptcha project site](https://www.google.com/recaptcha/) for more details. `, requires => [ @@ -674,9 +674,9 @@ our @options = ( ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this - from http://www.charliemouse.com/code/cambozola/ however if it - is not installed still images at a lower refresh rate can still - be viewed. + from the [cambozola project site](http://www.charliemouse.com/code/cambozola/). + However, if it is not installed still images at a lower refresh rate can + still be viewed. `, type => $types{boolean}, category => 'images', @@ -690,9 +690,9 @@ our @options = ( ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this - from http://www.charliemouse.com/code/cambozola/ however if it - is not installed still images at a lower refresh rate can still - be viewed. Leave this as 'cambozola.jar' if cambozola is + from the [cambozola project site](http://www.charliemouse.com/code/cambozola/). + However if it is not installed still images at a lower refresh rate can + still be viewed. Leave this as 'cambozola.jar' if cambozola is installed in the same directory as the ZoneMinder web client files. `, @@ -3908,7 +3908,7 @@ our @options = ( SSMTP is a lightweight and efficient method to send email. The SSMTP application is not installed by default. NEW_MAIL_MODULES must also be enabled. - Please visit: http://www.zoneminder.com/wiki/index.php/How_to_get_ssmtp_working_with_Zoneminder + Please visit the ZoneMinder [SSMTP Wiki page](http://www.zoneminder.com/wiki/index.php/How_to_get_ssmtp_working_with_Zoneminder) for setup and configuration help. `, type => $types{boolean}, From c34f899d3199e8749735ea71b4c878f9e002be1f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 4 Sep 2018 13:57:35 -0400 Subject: [PATCH 50/52] eliminate warning when no Storage area is set. --- scripts/ZoneMinder/lib/ZoneMinder/Event.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index fc09e3f3f..8469fae8a 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -423,7 +423,7 @@ sub delete_files { ( $event_path ) = ( $event_path =~ /^(.*)$/ ); # De-taint my $deleted = 0; - if ( $$Storage{Type} eq 's3fs' ) { + if ( $$Storage{Type} and ( $$Storage{Type} eq 's3fs' ) ) { my ( $aws_id, $aws_secret, $aws_host, $aws_bucket ) = ( $$Storage{Url} =~ /^\s*([^:]+):([^@]+)@([^\/]*)\/(.+)\s*$/ ); eval { require Net::Amazon::S3; @@ -444,7 +444,7 @@ sub delete_files { } }; Error($@) if $@; - } + } if ( ! $deleted ) { my $command = "/bin/rm -rf $storage_path/$event_path"; ZoneMinder::General::executeShellCommand( $command ); @@ -467,7 +467,7 @@ sub Storage { } if ( ! $_[0]{Storage} ) { $_[0]{Storage} = new ZoneMinder::Storage($_[0]{StorageId}); - } + } return $_[0]{Storage}; } @@ -488,7 +488,7 @@ sub check_for_in_filesystem { sub age { if ( ! $_[0]{age} ) { - if ( -e $_[0]->Path() ) { + if ( -e $_[0]->Path() ) { # $^T is the time the program began running. -M is program start time - file modification time in days $_[0]{age} = (time() - ($^T - ((-M $_[0]->Path() ) * 24*60*60))); } else { @@ -656,7 +656,7 @@ Debug("Files to move @files"); } # Succeeded in copying all files, so we may now update the Event. - $$self{StorageId} = $$NewStorage{Id}; + $$self{StorageId} = $$NewStorage{Id}; $$self{Storage} = $NewStorage; $error .= $self->save(); if ( $error ) { From 730e1fda3738c6da111e5a7bc534139ba4dad96e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 5 Sep 2018 10:14:45 -0400 Subject: [PATCH 51/52] We only use File::Slurp when moving files to s3fs so only require it if doing that --- scripts/ZoneMinder/lib/ZoneMinder/Event.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 8469fae8a..8eca805aa 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -35,7 +35,6 @@ require Date::Manip; require File::Find; require File::Path; require File::Copy; -require File::Slurp; require File::Basename; require Number::Bytes::Human; @@ -564,6 +563,7 @@ sub MoveTo { my ( $aws_id, $aws_secret, $aws_host, $aws_bucket ) = ( $$NewStorage{Url} =~ /^\s*([^:]+):([^@]+)@([^\/]*)\/(.+)\s*$/ ); eval { require Net::Amazon::S3; + require File::Slurp; my $s3 = Net::Amazon::S3->new( { aws_access_key_id => $aws_id, aws_secret_access_key => $aws_secret, From af32d59aa14a96dc9d54c22cb9bd279b2515b57c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 5 Sep 2018 10:18:09 -0400 Subject: [PATCH 52/52] add libhuman-bytes-perl and libfile-slurp-file --- distros/debian/control | 2 ++ 1 file changed, 2 insertions(+) diff --git a/distros/debian/control b/distros/debian/control index 20443f3f7..4c23ab367 100644 --- a/distros/debian/control +++ b/distros/debian/control @@ -42,6 +42,8 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} , libdata-dump-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl , libsys-cpu-perl, libsys-meminfo-perl , libdata-uuid-perl + ,libnumber-bytes-human-perl + ,libfile-slurp-perl , libpcre3 , ffmpeg | libav-tools, libavdevice53 | libavdevice55 | libavdevice57 , rsyslog | system-log-daemon