From de0a272b3dfe2268c6da072efe546f369d86a35d Mon Sep 17 00:00:00 2001 From: Daedilus Date: Mon, 16 Jul 2018 20:34:27 -0600 Subject: [PATCH 1/8] Added new control script for iPhone ip camera software https://itunes.apple.com/ca/app/ipcamera-high-end-network-camera/id570912928?mt=8 See https://forums.zoneminder.com/viewtopic.php?f=9&t=27386 for details. --- .../lib/ZoneMinder/Control/IPCAMIOS.pm | 326 ++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm new file mode 100644 index 000000000..8465ee472 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm @@ -0,0 +1,326 @@ +# ========================================================================== +# +# ZoneMinder iPhone Control Protocol Module, $Date: 2018-07-15 00:20:00 +0000 $, $Revision: 0003 $ +# Copyright (C) 2001-2008 Philip Coombes +# +# Modified for iPhone ipcamera for IOS BY PETER ZARGLIS n 2018-06-09 13:45:00 +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ========================================================================== +# +# This module contains the implementation of the iPhone ipcamera for IOS +# control protocol. +# +# ========================================================================== +package ZoneMinder::Control::IPCAMIOS; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# iPhone ipcamera for IOS Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); +use Time::HiRes qw( usleep ); + +my $loopfactor=100000; + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + my $logindetails = ""; + 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(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent" ); + + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + my $result = undef; + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + my $res = $self->{ua}->request($req); + if ( $res->is_success ) + { + $result = $res->decoded_content; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + return( $result ); +} +sub getDisplayAttr +{ + my $self = shift; + my $param = shift; + my $cmdget = "parameters?"; + my $resp = $self->sendCmd( $cmdget ); + my @fields = split(',',$resp); + my $response=$fields[$param]; + my @buffer=split(':',$response); + my $response2=$buffer[1]; + return ($response2); +} + +sub sleep +{ + +} +# Flip image vertically -> Horz -> off +sub moveConUp +{ + my $self = shift; + my $params = shift; + Debug( "Flip Image" ); + my $dvalue=$self->getDisplayAttr(3); + if ( $dvalue == 2 ) + { + $dvalue=0; + my $cmd = "parameters?flip=$dvalue"; + $self->sendCmd( $cmd ); + } + else + { + $dvalue=$dvalue+1; + my $cmd = "parameters?flip=$dvalue"; + $self->sendCmd( $cmd ); + } +} +# Change camera (front facing or back) +sub moveConDown +{ + my $self = shift; + my $params = shift; + Debug( "Change Camera" ); + my $dvalue=$self->getDisplayAttr(7); + if ( $dvalue == 0 ) + { + my $cmd = "parameters?camera=1"; + $self->sendCmd( $cmd ); + } + else + { + my $cmd = "parameters?camera=0"; + $self->sendCmd( $cmd ); + } +} +# Picture Orientation Clockwise +sub moveConRight +{ + my $self = shift; + my $params = shift; + Debug( "Orientation" ); + my $dvalue=$self->getDisplayAttr(10); + if ( $dvalue == 1 ) + { + $dvalue=4; + my $cmd = "parameters?rotation=$dvalue"; + $self->sendCmd( $cmd ); + } + else + { + $dvalue=$dvalue-1; + my $cmd = "parameters?rotation=$dvalue"; + $self->sendCmd( $cmd ); + } +} +# Picture Orientation Anti-Clockwise +sub moveConLeft +{ + my $self = shift; + my $params = shift; + Debug( "Orientation" ); + my $dvalue=$self->getDisplayAttr(10); + if ( $dvalue == 4 ) + { + $dvalue=1; + my $cmd = "parameters?rotation=$dvalue"; + $self->sendCmd( $cmd ); + } + else + { + $dvalue=$dvalue+1; + my $cmd = "parameters?rotation=$dvalue"; + $self->sendCmd( $cmd ); + } +} + +# presetHome is used to turn off Torch, unlock Focus, unlock Exposure, unlock white-balance, rotation, image flipping +# Just basically reset all the little variables and set it to medium quality +# Rotation = 0 means it will autoselect using built in detection +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "parameters?torch=0&focus=0&wb=0&exposure=0&rotation=0&flip=0&quality=0.5"; + $self->sendCmd( $cmd ); +} + +sub focusAbsNear +# Focus Un/Lock +{ + my $self = shift; + my $params = shift; + Debug( "Focus Un/Lock" ); + my $dvalue=$self->getDisplayAttr(2); + if ( $dvalue == 0 ) + { + my $cmd = "parameters?focus=1"; + $self->sendCmd( $cmd ); + } + else + { + my $cmd = "parameters?focus=0"; + $self->sendCmd( $cmd ); + } +} + +sub focusAbsFar +# Exposure Un/Lock +{ + my $self = shift; + my $params = shift; + Debug( "Exposure Un/Lock" ); + my $dvalue=$self->getDisplayAttr(11); + if ( $dvalue == 0 ) + { + my $cmd = "parameters?exposure=1"; + $self->sendCmd( $cmd ); + } + else + { + my $cmd = "parameters?exposure=0"; + $self->sendCmd( $cmd ); + } +} +# Increase stream Quality (from 0 to 10) +sub irisAbsOpen +{ + my $self = shift; + my $params = shift; + Debug( "Quality" ); + my $dvalue=$self->getDisplayAttr(8); + if ( $dvalue < 1 ) + { + $dvalue=$dvalue+0.1; + my $cmd = "parameters?quality=$dvalue"; + $self->sendCmd( $cmd ); + } +} + +# Decrease stream Quality (from 10 to 0) +sub irisAbsClose +{ + my $self = shift; + my $params = shift; + Debug( "Quality" ); + my $dvalue=$self->getDisplayAttr(8); + if ( $dvalue > 0 ) + { + $dvalue=$dvalue-0.1; + my $cmd = "parameters?quality=$dvalue"; + $self->sendCmd( $cmd ); + } +} +# White Balance Un/Lock +sub whiteAbsIn +{ + my $self = shift; + my $params = shift; + Debug( "White Balance" ); + my $dvalue=$self->getDisplayAttr(9); + if ( $dvalue == 0 ) + { + my $cmd = "parameters?wb=1"; + $self->sendCmd( $cmd ); + } + else + { + my $cmd = "parameters?wb=0"; + $self->sendCmd( $cmd ); + } +} + +# Torch control on/off +sub whiteAbsOut +{ + my $self = shift; + my $params = shift; + Debug( "Torch" ); + my $dvalue=$self->getDisplayAttr(5); + if ( $dvalue == 0 ) + { + my $cmd = "parameters?torch=1"; + $self->sendCmd( $cmd ); + } + else + { + my $cmd = "parameters?torch=0"; + $self->sendCmd( $cmd ); + } +} + +1; From d90e3daf801e95da6975244bdfd49b3530365ad3 Mon Sep 17 00:00:00 2001 From: Daedilus Date: Tue, 17 Jul 2018 08:31:55 -0600 Subject: [PATCH 2/8] Added default settings for control script IPCAMIOS as per comments in Pull #2161 --- db/zm_create.sql.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 83b75f768..cf7c1150d 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -777,7 +777,7 @@ INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-423','Ffmpeg','Reolink',0,0,1,1 INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-411','Ffmpeg','Reolink',0,0,1,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,'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); -- -- Add some monitor preset values -- From d45ca8880a87ab910844e0484eb221bb2fced210 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Tue, 17 Jul 2018 13:24:47 -0400 Subject: [PATCH 3/8] documentation for new login/logout APIs (#2163) --- docs/api.rst | 77 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 706748880..a5bdd35f3 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -13,8 +13,8 @@ The API is built in CakePHP and lives under the ``/api`` directory. It provides a RESTful service and supports CRUD (create, retrieve, update, delete) functions for Monitors, Events, Frames, Zones and Config. -Security -^^^^^^^^^ +Login, Logout & API Security +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The APIs tie into ZoneMinder's existing security model. This means if you have OPT_AUTH enabled, you need to log into ZoneMinder using the same browser you plan to use the APIs from. If you are developing an app that relies on the API, you need @@ -23,11 +23,32 @@ to do a POST login from the app into ZoneMinder before you can access the API. Then, you need to re-use the authentication information of the login (returned as cookie states) with subsequent APIs for the authentication information to flow through to the APIs. -This means if you plan to use cuRL to experiment with these APIs, you first need to do +This means if you plan to use cuRL to experiment with these APIs, you first need to login: + +**Login process for ZoneMinder v1.32.0 and above** :: - curl -d "username=XXXX&password=YYYY&action=login&view=console" -c cookies.txt http://yourzmip/zm/index.php + curl -XPOST -d "user=XXXX&pass=YYYY" -c cookies.txt http://yourzmip/zm/api/login.json + +Staring ZM 1.32.0, you also have a `logout` API that basically clears your session. It looks like this: + +:: + + curl -b cookies.txt http://yourzmip/zm/api/logout.json + + +**Login process for older versions of ZoneMinder** + +:: + + curl -d "username=XXXX&password=YYYY&action=login&view=console" -c cookies.txt http://yourzmip/zm/index.php + +The equivalent logout process for older versions of ZoneMinder is: + +:: + + curl -XPOST -d "username=XXXX&password=YYYY&action=logout&view=console" -b cookies.txt http://yourzmip/zm/index.php replacing *XXXX* and *YYYY* with your username and password, respectively. @@ -36,25 +57,55 @@ and the command will silently fail. What the "-c cookies.txt" does is store a cookie state reflecting that you have logged into ZM. You now need -to apply that cookie state to all subsequent APIs. You do that by using a '-b cookies.txt' to subsequent APIs if you are +to apply that cookie state to all subsequent APIs. You do that by using a '-b cookies.txt' to subsequent APIs if you are using CuRL like so: :: - curl -b cookies.txt http://yourzmip/zm/api/monitors.json + curl -b cookies.txt http://yourzmip/zm/api/monitors.json + +This would return a list of monitors and pass on the authentication information to the ZM API layer. + +A deeper dive into the login process +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As you might have seen above, there are two ways to login, one that uses the `login.json` API and the other that logs in using the ZM portal. If you are running ZoneMinder 1.32.0 and above, it is *strongly* recommended you use the `login.json` approach. The "old" approach will still work but is not as powerful as the API based login. Here are the reasons why: + + * The "old" approach basically uses the same login webpage (`index.php`) that a user would log into when viewing the ZM console. This is not really using an API and more importantly, if you have additional components like reCAPTCHA enabled, this will not work. Using the API approach is much cleaner and will work irrespective of reCAPTCHA + + * The new login API returns important information that you can use to stream videos as well, right after login. Consider for example, a typical response to the login API (`/login.json`): + +:: + + { + "credentials": "auth=f5b9cf48693fe8552503c8ABCD5", + "append_password": 0, + "version": "1.31.44", + "apiversion": "1.0" + } + +In this example I have `OPT_AUTH` enabled in ZoneMinder and it returns my credential key. You can then use this key to stream images like so: + +:: + + + +Where `authval` is the credentials returned to start streaming videos. + +The `append_password` field will contain 1 when it is necessary for you to append your ZM password. This is the case when you set `AUTH_RELAY` in ZM options to "plain", for example. In that case, the `credentials` field may contain something like `&user=admin&pass=` and you have to add your password to that string. + + +.. NOTE:: It is recommended you invoke the `login` API once every 60 minutes to make sure the session stays alive. The same is true if you use the old login method too. -This would return a list of monitors and pass on the authentication information to the ZM API layer. -So remember, if you are using authentication, please add a ``-b cookies.txt`` to each of the commands below if you are using -CuRL. If you are not using CuRL and writing your own app, you need to make sure you pass on cookies to subsequent requests -in your app. Examples (please read security notice above) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -You will see each URL ending in either ``.xml`` or ``.json``. This is the -format of the request, and it determines the format that any data returned to -you will be in. I like json, however you can use xml if you'd like. +Please remember, if you are using authentication, please add a ``-b cookies.txt`` to each of the commands below if you are using +CuRL. If you are not using CuRL and writing your own app, you need to make sure you pass on cookies to subsequent requests +in your app. + (In all examples, replace 'server' with IP or hostname & port where ZoneMinder is running) From 997aa6aa558601bfd0db25801d8c9265fe99f242 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Tue, 17 Jul 2018 13:57:20 -0400 Subject: [PATCH 4/8] fixed getCredentials not working if called directly --- web/api/app/Controller/AppController.php | 4 +--- web/api/app/Controller/HostController.php | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/api/app/Controller/AppController.php b/web/api/app/Controller/AppController.php index 06797ab5b..d83ce0825 100644 --- a/web/api/app/Controller/AppController.php +++ b/web/api/app/Controller/AppController.php @@ -72,10 +72,8 @@ class AppController extends Controller { } // We need to reject methods that are not authenticated // besides login and logout - if (strcasecmp($this->params->controller, "host") && - strcasecmp($this->params->action, "login") && + if ( strcasecmp($this->params->action, "login") && strcasecmp($this->params->action,"logout")) { - if (!$this->Session->read('user.Username')) { throw new UnauthorizedException(__('Not Authenticated')); return; diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php index 4daec2368..5b7c849fe 100644 --- a/web/api/app/Controller/HostController.php +++ b/web/api/app/Controller/HostController.php @@ -39,8 +39,8 @@ class HostController extends AppController { $zmOptAuth = $config['Config']['Value']; if ( $zmOptAuth == '1' ) { - require_once "../../../includes/auth.php"; + require_once "../../../includes/auth.php"; global $user; $user = $this->Session->read('user'); @@ -152,6 +152,8 @@ class HostController extends AppController { $isZmAuth = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')))['Config']['Value']; if ( $isZmAuth ) { + require_once "../../../includes/auth.php"; # in the event we directly call getCredentials.json + $this->Session->read('user'); # this is needed for command line/curl to recognize a session $zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value']; if ( $zmAuthRelay == 'hashed' ) { $zmAuthHashIps= $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value']; From dc57a3c91cf3ce8d509d16b3c0febf2b17f49aeb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 24 Jul 2018 16:41:09 -0400 Subject: [PATCH 5/8] fix spacing/quotes/google code style --- web/api/app/Controller/AppController.php | 25 +- web/api/app/Controller/EventsController.php | 185 ++++++------- web/api/app/Controller/MonitorsController.php | 51 ++-- .../app/Controller/ZonePresetsController.php | 169 ++++++------ web/api/app/Controller/ZonesController.php | 253 +++++++++--------- web/skins/classic/js/base.js | 2 +- 6 files changed, 345 insertions(+), 340 deletions(-) diff --git a/web/api/app/Controller/AppController.php b/web/api/app/Controller/AppController.php index d83ce0825..d48f853e3 100644 --- a/web/api/app/Controller/AppController.php +++ b/web/api/app/Controller/AppController.php @@ -66,23 +66,24 @@ class AppController extends Controller { $config = $this->Config->find('first', $options); $zmOptApi = $config['Config']['Value']; - if ($zmOptApi !='1') { + if ( $zmOptApi != '1' ) { 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; - } - + 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; + } } - } # end function beforeFilter() } diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php index fd0c4ef98..6b89d7c50 100644 --- a/web/api/app/Controller/EventsController.php +++ b/web/api/app/Controller/EventsController.php @@ -7,61 +7,61 @@ App::uses('AppController', 'Controller'); */ class EventsController extends AppController { -/** - * Components - * - * @var array - */ - public $components = array('RequestHandler', 'Scaler', 'Image', 'Paginator'); + /** + * Components + * + * @var array + */ + public $components = array('RequestHandler', 'Scaler', 'Image', 'Paginator'); public function beforeFilter() { parent::beforeFilter(); $canView = $this->Session->Read('eventPermission'); - if ($canView =='None') { + if ( $canView == 'None' ) { throw new UnauthorizedException(__('Insufficient Privileges')); return; } } -/** - * index method - * - * @return void - * This also creates a thumbnail for each event. - */ - public function index() { - $this->Event->recursive = -1; - - $allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); + /** + * index method + * + * @return void + * This also creates a thumbnail for each event. + */ + public function index() { + $this->Event->recursive = -1; - if (!empty($allowedMonitors)) { + $allowedMonitors = preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); + + if ( !empty($allowedMonitors) ) { $mon_options = array('Event.MonitorId' => $allowedMonitors); } else { - $mon_options=''; + $mon_options = ''; } - if ($this->request->params['named']) { - //$this->FilterComponent = $this->Components->load('Filter'); - //$conditions = $this->FilterComponent->buildFilter($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']; - } else { - $conditions = array(); - } + } else { + $conditions = array(); + } $settings = array( - // https://github.com/ZoneMinder/ZoneMinder/issues/995 - // 'limit' => $limit['ZM_WEB_EVENTS_PER_PAGE'], - // 25 events per page which is what the above - // default is, is way too low for an API - // changing this to 100 so we don't kill ZM - // with many event APIs. In future, we can - // make a nice ZM_API_ITEMS_PER_PAGE for all pagination - // API - - 'limit' => '100', - 'order' => array('StartTime'), - 'paramType' => 'querystring', + // https://github.com/ZoneMinder/ZoneMinder/issues/995 + // 'limit' => $limit['ZM_WEB_EVENTS_PER_PAGE'], + // 25 events per page which is what the above + // default is, is way too low for an API + // changing this to 100 so we don't kill ZM + // with many event APIs. In future, we can + // make a nice ZM_API_ITEMS_PER_PAGE for all pagination + // API + + 'limit' => '100', + 'order' => array('StartTime'), + 'paramType' => 'querystring', ); - if ( isset( $conditions['GroupId'] ) ) { + if ( isset($conditions['GroupId']) ) { $settings['joins'] = array( array( 'table' => 'Groups_Monitors', @@ -75,45 +75,45 @@ class EventsController extends AppController { } $settings['conditions'] = array($conditions, $mon_options); - // How many events to return - $this->loadModel('Config'); - $limit = $this->Config->find('list', array( - 'conditions' => array('Name' => 'ZM_WEB_EVENTS_PER_PAGE'), - 'fields' => array('Name', 'Value') - )); - $this->Paginator->settings = $settings; - $events = $this->Paginator->paginate('Event'); + // How many events to return + $this->loadModel('Config'); + $limit = $this->Config->find('list', array( + 'conditions' => array('Name' => 'ZM_WEB_EVENTS_PER_PAGE'), + 'fields' => array('Name', 'Value') + )); + $this->Paginator->settings = $settings; + $events = $this->Paginator->paginate('Event'); - // For each event, get the frameID which has the largest score - foreach ($events as $key => $value) { - $maxScoreFrameId = $this->getMaxScoreAlarmFrameId($value['Event']['Id']); - $events[$key]['Event']['MaxScoreFrameId'] = $maxScoreFrameId; - } + // For each event, get the frameID which has the largest score + foreach ($events as $key => $value) { + $maxScoreFrameId = $this->getMaxScoreAlarmFrameId($value['Event']['Id']); + $events[$key]['Event']['MaxScoreFrameId'] = $maxScoreFrameId; + } - $this->set(compact('events')); - } + $this->set(compact('events')); + } -/** - * view method - * - * @throws NotFoundException - * @param string $id - * @return void - */ - public function view($id = null) { + /** + * view method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function view($id = null) { $this->loadModel('Config'); $this->Event->recursive = 1; - if (!$this->Event->exists($id)) { + if ( !$this->Event->exists($id) ) { throw new NotFoundException(__('Invalid event')); } - $allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); + $allowedMonitors = preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); - if (!empty($allowedMonitors)) { + if ( !empty($allowedMonitors) ) { $mon_options = array('Event.MonitorId' => $allowedMonitors); } else { - $mon_options=''; + $mon_options = ''; } $options = array('conditions' => array(array('Event.' . $this->Event->primaryKey => $id), $mon_options)); @@ -149,14 +149,14 @@ class EventsController extends AppController { */ public function add() { - if ($this->Session->Read('eventPermission') != 'Edit') { + if ( $this->Session->Read('eventPermission') != 'Edit' ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } - if ($this->request->is('post')) { + if ( $this->request->is('post') ) { $this->Event->create(); - if ($this->Event->save($this->request->data)) { + if ( $this->Event->save($this->request->data) ) { return $this->flash(__('The event has been saved.'), array('action' => 'index')); } } @@ -173,18 +173,18 @@ class EventsController extends AppController { */ public function edit($id = null) { - if ($this->Session->Read('eventPermission') != 'Edit') { + if ( $this->Session->Read('eventPermission') != 'Edit' ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } $this->Event->id = $id; - if (!$this->Event->exists($id)) { + if ( !$this->Event->exists($id) ) { throw new NotFoundException(__('Invalid event')); } - if ($this->Event->save($this->request->data)) { + if ( $this->Event->save($this->request->data) ) { $message = 'Saved'; } else { $message = 'Error'; @@ -204,16 +204,16 @@ class EventsController extends AppController { * @return void */ public function delete($id = null) { - if ($this->Session->Read('eventPermission') != 'Edit') { + if ( $this->Session->Read('eventPermission') != 'Edit' ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } $this->Event->id = $id; - if (!$this->Event->exists()) { + if ( !$this->Event->exists() ) { throw new NotFoundException(__('Invalid event')); } $this->request->allowMethod('post', 'delete'); - if ($this->Event->delete()) { + if ( $this->Event->delete() ) { //$this->loadModel('Frame'); //$this->Event->Frame->delete(); return $this->flash(__('The event has been deleted.'), array('action' => 'index')); @@ -228,7 +228,7 @@ class EventsController extends AppController { foreach ($this->params['named'] as $param_name => $value) { // Transform params into mysql - if (preg_match("/interval/i", $value, $matches)) { + if ( preg_match('/interval/i', $value, $matches) ) { $condition = array("$param_name >= (date_sub(now(), $value))"); } else { $condition = array($param_name => $value); @@ -254,9 +254,9 @@ class EventsController extends AppController { $this->Event->recursive = -1; $results = array(); - $moreconditions =""; + $moreconditions = ''; foreach ($this->request->params['named'] as $name => $param) { - $moreconditions = $moreconditions . " AND ".$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;"); @@ -275,7 +275,7 @@ class EventsController extends AppController { public function createThumbnail($id = null) { $this->Event->recursive = -1; - if (!$this->Event->exists($id)) { + if ( !$this->Event->exists($id) ) { throw new NotFoundException(__('Invalid event')); } @@ -285,13 +285,13 @@ class EventsController extends AppController { // Find the max Frame for this Event. Error out otherwise. $this->loadModel('Frame'); - if (! $frame = $this->Frame->find('first', array( + if ( !( $frame = $this->Frame->find('first', array( 'conditions' => array( 'EventId' => $event['Event']['Id'], 'Score' => $event['Event']['MaxScore'] ) - ))) { - throw new NotFoundException(__("Can not find Frame for Event " . $event['Event']['Id'])); + ))) ) { + throw new NotFoundException(__('Can not find Frame for Event ' . $event['Event']['Id'])); } $this->loadModel('Config'); @@ -304,14 +304,15 @@ class EventsController extends AppController { $config = $this->Config->find('list', array( 'conditions' => array('OR' => array( - 'Name' => array('ZM_WEB_LIST_THUMB_WIDTH', - 'ZM_WEB_LIST_THUMB_HEIGHT', - 'ZM_EVENT_IMAGE_DIGITS', - 'ZM_DIR_IMAGES', - $thumbs, - 'ZM_DIR_EVENTS' - ) - )), + 'Name' => array( + 'ZM_WEB_LIST_THUMB_WIDTH', + 'ZM_WEB_LIST_THUMB_HEIGHT', + 'ZM_EVENT_IMAGE_DIGITS', + 'ZM_DIR_IMAGES', + $thumbs, + 'ZM_DIR_EVENTS' + ) + )), 'fields' => array('Name', 'Value') )); $config['ZM_WEB_SCALE_THUMBS'] = $config[$thumbs]; @@ -340,7 +341,7 @@ class EventsController extends AppController { public function archive($id = null) { $this->Event->recursive = -1; - if (!$this->Event->exists($id)) { + if ( !$this->Event->exists($id) ) { throw new NotFoundException(__('Invalid event')); } @@ -365,7 +366,7 @@ class EventsController extends AppController { public function getMaxScoreAlarmFrameId($id = null) { $this->Event->recursive = -1; - if (!$this->Event->exists($id)) { + if ( !$this->Event->exists($id) ) { throw new NotFoundException(__('Invalid event')); } @@ -382,7 +383,7 @@ class EventsController extends AppController { 'Score' => $event['Event']['MaxScore'] ) ))) { - throw new NotFoundException(__("Can not find Frame for Event " . $event['Event']['Id'])); + throw new NotFoundException(__('Can not find Frame for Event ' . $event['Event']['Id'])); } return $frame['Frame']['Id']; } diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 5801c1e9e..05756ede0 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -18,6 +18,7 @@ class MonitorsController extends AppController { public function beforeRender() { $this->set($this->Monitor->enumValues()); } + public function beforeFilter() { parent::beforeFilter(); $canView = $this->Session->Read('monitorPermission'); @@ -35,7 +36,7 @@ class MonitorsController extends AppController { public function index() { $this->Monitor->recursive = 0; - 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']; @@ -49,7 +50,7 @@ class MonitorsController extends AppController { } $find_array = array('conditions'=>$conditions,'contain'=>array('Group')); - if ( isset( $conditions['GroupId'] ) ) { + if ( isset($conditions['GroupId']) ) { $find_array['joins'] = array( array( 'table' => 'Groups_Monitors', @@ -84,11 +85,11 @@ class MonitorsController extends AppController { */ public function view($id = null) { $this->Monitor->recursive = 0; - if (!$this->Monitor->exists($id)) { + 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)) { + $allowedMonitors=preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); + if ( !empty($allowedMonitors) ) { $restricted = array('Monitor.' . $this->Monitor->primaryKey => $allowedMonitors); } else { $restricted = ''; @@ -115,12 +116,12 @@ class MonitorsController extends AppController { if ( $this->request->is('post') ) { if ( $this->Session->Read('systemPermission') != 'Edit' ) { - throw new UnauthorizedException(__('Insufficient privileges')); + throw new UnauthorizedException(__('Insufficient privileges')); return; } $this->Monitor->create(); - if ($this->Monitor->save($this->request->data)) { + if ( $this->Monitor->save($this->request->data) ) { $this->daemonControl($this->Monitor->id, 'start'); //return $this->flash(__('The monitor has been saved.'), array('action' => 'index')); $message = 'Saved'; @@ -144,10 +145,10 @@ class MonitorsController extends AppController { public function edit($id = null) { $this->Monitor->id = $id; - if (!$this->Monitor->exists($id)) { + if ( !$this->Monitor->exists($id) ) { throw new NotFoundException(__('Invalid monitor')); } - if ($this->Session->Read('monitorPermission') != 'Edit') { + if ( $this->Session->Read('monitorPermission') != 'Edit' ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -163,9 +164,17 @@ class MonitorsController extends AppController { // - restart or stop this monitor after change $func = $Monitor['Function']; // We don't pass the request data as the monitor object because it may be a subset of the full monitor array - $this->daemonControl( $this->Monitor->id, 'stop' ); - if ( ( $func != 'None' ) and ( (!defined('ZM_SERVER_ID')) or ($Monitor['ServerId']==ZM_SERVER_ID) ) ) { - $this->daemonControl( $this->Monitor->id, 'start' ); + $this->daemonControl($this->Monitor->id, 'stop'); + if ( + ( $func != 'None' ) + and + ( + (!defined('ZM_SERVER_ID')) + or + ($Monitor['ServerId']==ZM_SERVER_ID) + ) + ) { + $this->daemonControl($this->Monitor->id, 'start'); } } else { $message = 'Error ' . print_r($this->Monitor->invalidFields(), true); @@ -187,10 +196,10 @@ class MonitorsController extends AppController { */ public function delete($id = null) { $this->Monitor->id = $id; - if (!$this->Monitor->exists()) { + if ( !$this->Monitor->exists() ) { throw new NotFoundException(__('Invalid monitor')); } - if ($this->Session->Read('systemPermission') != 'Edit') { + if ( $this->Session->Read('systemPermission') != 'Edit' ) { throw new UnauthorizedException(__('Insufficient privileges')); return; } @@ -198,7 +207,7 @@ class MonitorsController extends AppController { $this->daemonControl($this->Monitor->id, 'stop'); - if ($this->Monitor->delete()) { + if ( $this->Monitor->delete() ) { return $this->flash(__('The monitor has been deleted.'), array('action' => 'index')); } else { return $this->flash(__('The monitor could not be deleted. Please, try again.'), array('action' => 'index')); @@ -226,7 +235,7 @@ class MonitorsController extends AppController { public function alarm() { $id = $this->request->params['named']['id']; $cmd = strtolower($this->request->params['named']['command']); - if (!$this->Monitor->exists($id)) { + if ( !$this->Monitor->exists($id) ) { throw new NotFoundException(__('Invalid monitor')); } if ( $cmd != 'on' && $cmd != 'off' && $cmd != 'status' ) { @@ -252,19 +261,19 @@ class MonitorsController extends AppController { // form auth key based on auth credentials $this->loadModel('Config'); $options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')); - $config = $this->Config->find('first', $options); + $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); + $config = $this->Config->find('first', $options); $zmAuthRelay = $config['Config']['Value']; - $auth=''; + $auth = ''; if ( $zmOptAuth ) { if ( $zmAuthRelay == 'hashed' ) { $options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_SECRET')); - $config = $this->Config->find('first', $options); + $config = $this->Config->find('first', $options); $zmAuthHashSecret = $config['Config']['Value']; $time = localtime(); @@ -293,7 +302,7 @@ class MonitorsController extends AppController { $id = $this->request->params['named']['id']; $daemon = $this->request->params['named']['daemon']; - if (!$this->Monitor->exists($id)) { + if ( !$this->Monitor->exists($id) ) { throw new NotFoundException(__('Invalid monitor')); } diff --git a/web/api/app/Controller/ZonePresetsController.php b/web/api/app/Controller/ZonePresetsController.php index b89a6c75d..e26732eb8 100644 --- a/web/api/app/Controller/ZonePresetsController.php +++ b/web/api/app/Controller/ZonePresetsController.php @@ -8,92 +8,93 @@ App::uses('AppController', 'Controller'); */ class ZonePresetsController extends AppController { -/** - * Components - * - * @var array - */ - public $components = array('RequestHandler'); + /** + * Components + * + * @var array + */ + public $components = array('RequestHandler'); -/** - * index method - * - * @return void - */ - public function index() { - $zonePresets = $this->ZonePreset->find('all'); - $this->set(array( - 'zonePresets' => $zonePresets, - '_serialize' => array('zonePresets') - )); - } + /** + * index method + * + * @return void + */ + public function index() { + $zonePresets = $this->ZonePreset->find('all'); + $this->set(array( + 'zonePresets' => $zonePresets, + '_serialize' => array('zonePresets') + )); + } -/** - * view method - * - * @throws NotFoundException - * @param string $id - * @return void - */ - public function view($id = null) { - if (!$this->ZonePreset->exists($id)) { - throw new NotFoundException(__('Invalid zone preset')); - } - $options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id)); - $this->set('zonePreset', $this->ZonePreset->find('first', $options)); - } + /** + * view method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function view($id = null) { + if ( !$this->ZonePreset->exists($id) ) { + throw new NotFoundException(__('Invalid zone preset')); + } + $options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id)); + $this->set('zonePreset', $this->ZonePreset->find('first', $options)); + } -/** - * add method - * - * @return void - */ - public function add() { - if ($this->request->is('post')) { - $this->ZonePreset->create(); - if ($this->ZonePreset->save($this->request->data)) { - return $this->flash(__('The zone preset has been saved.'), array('action' => 'index')); - } - } - } + /** + * add method + * + * @return void + */ + public function add() { + if ( $this->request->is('post') ) { + $this->ZonePreset->create(); + if ( $this->ZonePreset->save($this->request->data) ) { + return $this->flash(__('The zone preset has been saved.'), array('action' => 'index')); + } + } + } -/** - * edit method - * - * @throws NotFoundException - * @param string $id - * @return void - */ - public function edit($id = null) { - if (!$this->ZonePreset->exists($id)) { - throw new NotFoundException(__('Invalid zone preset')); - } - if ($this->request->is(array('post', 'put'))) { - if ($this->ZonePreset->save($this->request->data)) { - return $this->flash(__('The zone preset has been saved.'), array('action' => 'index')); - } - } else { - $options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id)); - $this->request->data = $this->ZonePreset->find('first', $options); - } - } + /** + * edit method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function edit($id = null) { + if ( !$this->ZonePreset->exists($id) ) { + throw new NotFoundException(__('Invalid zone preset')); + } + if ( $this->request->is(array('post', 'put')) ) { + if ( $this->ZonePreset->save($this->request->data) ) { + return $this->flash(__('The zone preset has been saved.'), array('action' => 'index')); + } + } else { + $options = array('conditions' => array('ZonePreset.' . $this->ZonePreset->primaryKey => $id)); + $this->request->data = $this->ZonePreset->find('first', $options); + } + } -/** - * delete method - * - * @throws NotFoundException - * @param string $id - * @return void - */ - public function delete($id = null) { - $this->ZonePreset->id = $id; - if (!$this->ZonePreset->exists()) { - throw new NotFoundException(__('Invalid zone preset')); - } - $this->request->allowMethod('post', 'delete'); - if ($this->ZonePreset->delete()) { - return $this->flash(__('The zone preset has been deleted.'), array('action' => 'index')); - } else { - return $this->flash(__('The zone preset could not be deleted. Please, try again.'), array('action' => 'index')); - } - }} + /** + * delete method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function delete($id = null) { + $this->ZonePreset->id = $id; + if ( !$this->ZonePreset->exists() ) { + throw new NotFoundException(__('Invalid zone preset')); + } + $this->request->allowMethod('post', 'delete'); + if ( $this->ZonePreset->delete() ) { + return $this->flash(__('The zone preset has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The zone preset could not be deleted. Please, try again.'), array('action' => 'index')); + } + } +} // end class ZonePresetsController diff --git a/web/api/app/Controller/ZonesController.php b/web/api/app/Controller/ZonesController.php index 5fbadc2ed..64cd7b144 100644 --- a/web/api/app/Controller/ZonesController.php +++ b/web/api/app/Controller/ZonesController.php @@ -7,148 +7,141 @@ App::uses('AppController', 'Controller'); */ class ZonesController extends AppController { -/** - * Components - * - * @var array - */ -public $components = array('RequestHandler'); + /** + * Components + * + * @var array + */ + public $components = array('RequestHandler'); -public function beforeFilter() { - parent::beforeFilter(); - $canView = $this->Session->Read('monitorPermission'); - if ($canView =='None') - { - throw new UnauthorizedException(__('Insufficient Privileges')); - return; - } + public function beforeFilter() { + parent::beforeFilter(); + $canView = $this->Session->Read('monitorPermission'); + if ( $canView =='None' ) { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } + } -} - -// Find all zones which belong to a MonitorId -public function forMonitor($id = null) { + // Find all zones which belong to a MonitorId + public function forMonitor($id = null) { $this->loadModel('Monitor'); - if (!$this->Monitor->exists($id)) { - throw new NotFoundException(__('Invalid monitor')); + if ( !$this->Monitor->exists($id) ) { + throw new NotFoundException(__('Invalid monitor')); } $this->Zone->recursive = -1; $zones = $this->Zone->find('all', array( - 'conditions' => array('MonitorId' => $id) + 'conditions' => array('MonitorId' => $id) )); $this->set(array( - 'zones' => $zones, - '_serialize' => array('zones') + 'zones' => $zones, + '_serialize' => array('zones') )); -} -public function index() { + } + + public function index() { $this->Zone->recursive = -1; - - $allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY); - if (!empty($allowedMonitors)) - { - $mon_options = array('Zones.MonitorId' => $allowedMonitors); - } - else - { - $mon_options=''; + + $allowedMonitors = preg_split('@,@', $this->Session->Read('allowedMonitors'), NULL, PREG_SPLIT_NO_EMPTY); + if ( !empty($allowedMonitors) ) { + $mon_options = array('Zones.MonitorId' => $allowedMonitors); + } else { + $mon_options = ''; } $zones = $this->Zone->find('all',$mon_options); $this->set(array( - 'zones' => $zones, - '_serialize' => array('zones') + 'zones' => $zones, + '_serialize' => array('zones') )); -} -/** - * add method - * - * @return void - */ - public function add() { - if ($this->request->is('post')) { - $this->Zone->create(); - if ($this->Zone->save($this->request->data)) { - return $this->flash(__('The zone has been saved.'), array('action' => 'index')); - } - } - $monitors = $this->Zone->Monitor->find('list'); - $this->set(compact('monitors')); - } - -/** - * edit method - * - * @throws NotFoundException - * @param string $id - * @return void - */ - public function edit($id = null) { - $this->Zone->id = $id; - - if (!$this->Zone->exists($id)) { - throw new NotFoundException(__('Invalid zone')); - } - if ($this->request->is(array('post', 'put'))) { - if ($this->Zone->save($this->request->data)) { - return $this->flash(__('The zone has been saved.'), array('action' => 'index')); - } - } else { - $options = array('conditions' => array('Zone.' . $this->Zone->primaryKey => $id)); - $this->request->data = $this->Zone->find('first', $options); - } - $monitors = $this->Zone->Monitor->find('list'); - $this->set(compact('monitors')); - } - -/** - * delete method - * - * @throws NotFoundException - * @param string $id - * @return void - */ - public function delete($id = null) { - $this->Zone->id = $id; - if (!$this->Zone->exists()) { - throw new NotFoundException(__('Invalid zone')); - } - $this->request->allowMethod('post', 'delete'); - if ($this->Zone->delete()) { - return $this->flash(__('The zone has been deleted.'), array('action' => 'index')); - } else { - return $this->flash(__('The zone could not be deleted. Please, try again.'), array('action' => 'index')); - } - } - - - - public function createZoneImage( $id = null ) { - $this->loadModel('Monitor'); - $this->Monitor->id = $id; - if (!$this->Monitor->exists()) { - throw new NotFoundException(__('Invalid zone')); - } - - - $this->loadModel('Config'); - $zm_dir_images = $this->Config->find('list', array( - 'conditions' => array('Name' => 'ZM_DIR_IMAGES'), - 'fields' => array('Name', 'Value') - )); - - $zm_dir_images = $zm_dir_images['ZM_DIR_IMAGES']; - $zm_path_web = Configure::read('ZM_PATH_WEB'); - $zm_path_bin = Configure::read('ZM_PATH_BIN'); - $images_path = "$zm_path_web/$zm_dir_images"; - - chdir($images_path); - - $command = escapeshellcmd("$zm_path_bin/zmu -z -m $id"); - system( $command, $status ); - - $this->set(array( - 'status' => $status, - '_serialize' => array('status') - )); - - } + } + + /** + * add method + * + * @return void + */ + public function add() { + if ( $this->request->is('post') ) { + $this->Zone->create(); + if ( $this->Zone->save($this->request->data) ) { + return $this->flash(__('The zone has been saved.'), array('action' => 'index')); + } + } + $monitors = $this->Zone->Monitor->find('list'); + $this->set(compact('monitors')); + } + + /** + * edit method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function edit($id = null) { + $this->Zone->id = $id; + + if ( !$this->Zone->exists($id) ) { + throw new NotFoundException(__('Invalid zone')); + } + if ( $this->request->is(array('post', 'put')) ) { + if ( $this->Zone->save($this->request->data) ) { + return $this->flash(__('The zone has been saved.'), array('action' => 'index')); + } + } else { + $options = array('conditions' => array('Zone.' . $this->Zone->primaryKey => $id)); + $this->request->data = $this->Zone->find('first', $options); + } + $monitors = $this->Zone->Monitor->find('list'); + $this->set(compact('monitors')); + } + + /** + * delete method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function delete($id = null) { + $this->Zone->id = $id; + if ( !$this->Zone->exists() ) { + throw new NotFoundException(__('Invalid zone')); + } + $this->request->allowMethod('post', 'delete'); + if ( $this->Zone->delete() ) { + return $this->flash(__('The zone has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The zone could not be deleted. Please, try again.'), array('action' => 'index')); + } + } + + public function createZoneImage($id = null) { + $this->loadModel('Monitor'); + $this->Monitor->id = $id; + if ( !$this->Monitor->exists() ) { + throw new NotFoundException(__('Invalid zone')); + } + + $this->loadModel('Config'); + $zm_dir_images = $this->Config->find('list', array( + 'conditions' => array('Name' => 'ZM_DIR_IMAGES'), + 'fields' => array('Name', 'Value') + )); + + $zm_dir_images = $zm_dir_images['ZM_DIR_IMAGES']; + $zm_path_web = Configure::read('ZM_PATH_WEB'); + $zm_path_bin = Configure::read('ZM_PATH_BIN'); + $images_path = "$zm_path_web/$zm_dir_images"; + + chdir($images_path); + + $command = escapeshellcmd("$zm_path_bin/zmu -z -m $id"); + system($command, $status); + + $this->set(array( + 'status' => $status, + '_serialize' => array('status') + )); + } } diff --git a/web/skins/classic/js/base.js b/web/skins/classic/js/base.js index b19ca29a0..71289b6d2 100644 --- a/web/skins/classic/js/base.js +++ b/web/skins/classic/js/base.js @@ -54,7 +54,7 @@ var popupSizes = { 'monitorselect':{ 'width': 160, 'height': 200 }, 'montage': { 'width': -1, 'height': -1 }, 'onvifprobe': { 'width': 700, 'height': 550 }, - 'optionhelp': { 'width': 400, 'height': 320 }, + 'optionhelp': { 'width': 400, 'height': 400 }, 'options': { 'width': 1000, 'height': 660 }, 'preset': { 'width': 300, 'height': 220 }, 'server': { 'width': 600, 'height': 405 }, From 6ab1c3ced8559e6a2d1ba71fbedb2cabdc1da90b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 25 Jul 2018 09:39:08 -0400 Subject: [PATCH 6/8] proper case table header --- web/skins/classic/views/options.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index 31c1f57cb..2a17cf0b9 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -260,8 +260,8 @@ foreach( array_map( 'basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI - - + + From 00bdfdcb16e0dd723bdfb1c1e3524cb193582b2c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 25 Jul 2018 09:39:24 -0400 Subject: [PATCH 7/8] increase height of function popup so that dropdown options fit in it --- web/skins/classic/js/base.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/js/base.js b/web/skins/classic/js/base.js index 71289b6d2..9eb93ee77 100644 --- a/web/skins/classic/js/base.js +++ b/web/skins/classic/js/base.js @@ -41,7 +41,7 @@ var popupSizes = { 'filter': { 'width': 900, 'height': 700 }, 'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 200 }, 'frames': { 'width': 600, 'height': 600 }, - 'function': { 'width': 350, 'height': 160 }, + 'function': { 'width': 350, 'height': 260 }, 'group': { 'width': 760, 'height': 600 }, 'groups': { 'width': 540, 'height': 420 }, 'image': { 'addWidth': 48, 'addHeight': 80 }, From 2ff47e04da8f9c475e3d450cb5ea92945459f886 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 25 Jul 2018 17:04:42 -0400 Subject: [PATCH 8/8] the updated video-js.css puts the fonts into a font dir. --- web/skins/classic/js/{ => font}/vjs.eot | Bin web/skins/classic/js/{ => font}/vjs.ttf | Bin web/skins/classic/js/{ => font}/vjs.woff | Bin 3 files changed, 0 insertions(+), 0 deletions(-) rename web/skins/classic/js/{ => font}/vjs.eot (100%) rename web/skins/classic/js/{ => font}/vjs.ttf (100%) rename web/skins/classic/js/{ => font}/vjs.woff (100%) diff --git a/web/skins/classic/js/vjs.eot b/web/skins/classic/js/font/vjs.eot similarity index 100% rename from web/skins/classic/js/vjs.eot rename to web/skins/classic/js/font/vjs.eot diff --git a/web/skins/classic/js/vjs.ttf b/web/skins/classic/js/font/vjs.ttf similarity index 100% rename from web/skins/classic/js/vjs.ttf rename to web/skins/classic/js/font/vjs.ttf diff --git a/web/skins/classic/js/vjs.woff b/web/skins/classic/js/font/vjs.woff similarity index 100% rename from web/skins/classic/js/vjs.woff rename to web/skins/classic/js/font/vjs.woff