From eee3729b854cb6e40d9f5fb1698c1e2ea60e35aa Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 4 Dec 2019 22:23:55 -0500 Subject: [PATCH 01/71] dirty fix filtering Monitors by GroupId. Change occurrences of GroupId to ' ' as that is what the key is in conditions. Please note that other operators like != won't work. --- web/api/app/Controller/MonitorsController.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 3be9166b8..eb229975b 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -36,7 +36,7 @@ class MonitorsController extends AppController { * @return void */ public function index() { - $this->Monitor->recursive = 0; + $this->Monitor->recursive = 1; if ( $this->request->params['named'] ) { $this->FilterComponent = $this->Components->load('Filter'); @@ -44,21 +44,21 @@ class MonitorsController extends AppController { } else { $conditions = array(); } - 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')); - if ( isset($conditions['GroupId']) ) { + $find_array = array('conditions'=>&$conditions,'contain'=>array('Group')); + if ( isset($conditions['`GroupId` ']) ) { $find_array['joins'] = array( array( 'table' => 'Groups_Monitors', 'type' => 'inner', 'conditions' => array( - 'Groups_Monitors.MonitorId = Monitor.Id' + 'Groups_Monitors.MonitorId = Monitor.Id', + 'Groups_Monitors.GroupId' => $conditions['`GroupId` '] ), ), //array( @@ -70,6 +70,7 @@ class MonitorsController extends AppController { //), //) ); + unset($conditions['`GroupId` ']); } $monitors = $this->Monitor->find('all',$find_array); $this->set(array( From 4b786eaad57397be54bde84db0a103bd3d1c3702 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 6 Dec 2019 14:31:06 -0500 Subject: [PATCH 02/71] fix errors when ['id'] does not exist, and move the definition of values up because we use it outside the block it is defined in --- web/ajax/status.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/ajax/status.php b/web/ajax/status.php index a553eaa04..2725dcce8 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -83,8 +83,8 @@ $statusData = array( 'MinEventId' => array( 'sql' => '(SELECT min(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id' ), 'MaxEventId' => array( 'sql' => '(SELECT max(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id' ), 'TotalEvents' => array( 'sql' => '(SELECT count(Events.Id) FROM Events WHERE Events.MonitorId = Monitors.Id' ), - 'Status' => array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -s' ), - 'FrameRate' => array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -f' ), + 'Status' => (isset($_REQUEST['id'])?array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -s' ):null), + 'FrameRate' => (isset($_REQUEST['id'])?array( 'zmu' => '-m '.escapeshellarg($_REQUEST['id'][0]).' -f' ):null), ), ), 'events' => array( @@ -204,6 +204,7 @@ function collectData() { $fieldSql = array(); $joinSql = array(); $groupSql = array(); + $values = array(); $elements = &$entitySpec['elements']; $lc_elements = array_change_key_case( $elements ); @@ -258,7 +259,6 @@ function collectData() { if ( $id && !empty($entitySpec['selector']) ) { $index = 0; $where = array(); - $values = array(); foreach( $entitySpec['selector'] as $selIndex => $selector ) { $selectorParamName = ':selector' . $selIndex; if ( is_array( $selector ) ) { From bcda92058eef2db2d202687939556c65bad18d98 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 20 Dec 2019 14:56:01 -0500 Subject: [PATCH 03/71] proper way to make cakephp filter by group. Make Group containable, always add the join --- web/api/app/Controller/MonitorsController.php | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index eb229975b..07167b33a 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -36,7 +36,7 @@ class MonitorsController extends AppController { * @return void */ public function index() { - $this->Monitor->recursive = 1; + $this->Monitor->recursive = 0; if ( $this->request->params['named'] ) { $this->FilterComponent = $this->Components->load('Filter'); @@ -50,28 +50,19 @@ class MonitorsController extends AppController { $conditions['Monitor.Id' ] = $allowedMonitors; } - $find_array = array('conditions'=>&$conditions,'contain'=>array('Group')); - if ( isset($conditions['`GroupId` ']) ) { - $find_array['joins'] = array( + $find_array = array( + 'conditions' => &$conditions, + 'contain' => array('Group'), + 'joins' => array( array( 'table' => 'Groups_Monitors', - 'type' => 'inner', + 'type' => 'inner', 'conditions' => array( 'Groups_Monitors.MonitorId = Monitor.Id', - 'Groups_Monitors.GroupId' => $conditions['`GroupId` '] ), ), - //array( - //'table' => 'Groups', - //'type' => 'inner', - //'conditions' => array( - //'Groups.Id = Groups_Monitors.GroupId', - //'Groups.Id' => $this->request->params['GroupId'], - //), - //) - ); - unset($conditions['`GroupId` ']); - } + ) + ); $monitors = $this->Monitor->find('all',$find_array); $this->set(array( 'monitors' => $monitors, From d25a91ad1394efb260873b15ac510e7ca7f67414 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 20 Dec 2019 14:56:14 -0500 Subject: [PATCH 04/71] Make Group containable --- web/api/app/Model/Group.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/api/app/Model/Group.php b/web/api/app/Model/Group.php index 8d8f533ca..04d783b14 100644 --- a/web/api/app/Model/Group.php +++ b/web/api/app/Model/Group.php @@ -77,4 +77,5 @@ class Group extends AppModel { 'counterQuery' => '' ), ); + var $actsAs = array( 'Containable' ); } From fc017893bcba7973542b6ea9f3c2c088d8dfc944 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 20 Dec 2019 16:09:34 -0500 Subject: [PATCH 05/71] Sort the log filtering options. Fixes #2756 --- web/ajax/log.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index ef2e450f2..36a29adc3 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -41,7 +41,7 @@ function buildLogQuery($action) { } foreach ( $filter as $field=>$value ) { - if ( ! in_array($field, $filterFields) ) { + if ( !in_array($field, $filterFields) ) { ZM\Error("'$field' is not in valid filter fields " . print_r($filterField,true)); continue; } @@ -58,7 +58,7 @@ function buildLogQuery($action) { $sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit; return array('sql'=>$sql, 'values'=>$values); -} +} # function buildLogQuery($action) switch ( $_REQUEST['task'] ) { case 'create' : @@ -70,14 +70,16 @@ switch ( $_REQUEST['task'] ) { $string = $_POST['message']; $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : ''; - if ( !empty( $_POST['line'] ) ) + if ( !empty( $_POST['line'] ) ) { $line = validInt($_POST['line']); - else + } else { $line = NULL; + } $levels = array_flip(ZM\Logger::$codes); - if ( !isset($levels[$_POST['level']]) ) + if ( !isset($levels[$_POST['level']]) ) { ZM\Panic('Unexpected logger level '.$_POST['level']); + } $level = $levels[$_POST['level']]; ZM\Logger::fetch()->logPrint($level, $string, $file, $line); } @@ -141,6 +143,10 @@ switch ( $_REQUEST['task'] ) { $logs[] = $log; } + foreach ( $options as $field => $values ) { + asort($options[$field]); + } + $available = count($logs); ajaxResponse( array( 'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG)?strftime(DATE_FMT_CONSOLE_LONG):date(DATE_FMT_CONSOLE_LONG), From 23dde04725045fe38e2f687782e9439211aac5e1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 20 Dec 2019 16:10:30 -0500 Subject: [PATCH 06/71] remove timeout on changing runstate. --- web/skins/classic/views/js/state.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/state.js b/web/skins/classic/views/js/state.js index 7165c690c..e8b4db36d 100644 --- a/web/skins/classic/views/js/state.js +++ b/web/skins/classic/views/js/state.js @@ -54,7 +54,7 @@ $j(document).ready(function() { url: thisUrl, data: formData, dataType: 'html', - enocde: true + timeout: 0 }).done(function(data) { location.reload(); }); From 5a45835006df7532ef5a313849617fc14f4f8a8a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 20 Dec 2019 16:11:10 -0500 Subject: [PATCH 07/71] break up long lines --- web/skins/classic/views/log.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/log.php b/web/skins/classic/views/log.php index 7dd83ef2a..044a3e788 100644 --- a/web/skins/classic/views/log.php +++ b/web/skins/classic/views/log.php @@ -122,9 +122,12 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
- - - + + + + + +
From 63d20a1514003a7cf83a2ac8dd6f1276641bdee8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 20 Dec 2019 16:11:24 -0500 Subject: [PATCH 08/71] Move hidden inputs to top of form --- web/skins/classic/views/state.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/state.php b/web/skins/classic/views/state.php index 16c7708ed..b5c069600 100644 --- a/web/skins/classic/views/state.php +++ b/web/skins/classic/views/state.php @@ -25,6 +25,10 @@ if ( !canEdit('System') ) { ?> - - @@ -319,23 +317,28 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $ } function updateSelected() { + # Turn them all off, then selectively turn the checked ones back on dbQuery('UPDATE `Users` SET `APIEnabled`=0'); - foreach ( $_REQUEST["tokenUids"] as $markUid ) { - $minTime = time(); - dbQuery('UPDATE `Users` SET `TokenMinExpiry`=? WHERE `Id`=?', array($minTime, $markUid)); + + if ( isset($_REQUEST['tokenUids']) ) { + foreach ( $_REQUEST['tokenUids'] as $markUid ) { + $minTime = time(); + dbQuery('UPDATE `Users` SET `TokenMinExpiry`=? WHERE `Id`=?', array($minTime, $markUid)); + } } - foreach ( $_REQUEST["apiUids"] as $markUid ) { - dbQuery('UPDATE `Users` SET `APIEnabled`=1 WHERE `Id`=?', array($markUid)); - + if ( isset($_REQUEST['apiUids']) ) { + foreach ( $_REQUEST['apiUids'] as $markUid ) { + dbQuery('UPDATE `Users` SET `APIEnabled`=1 WHERE `Id`=?', array($markUid)); + } } echo ''.translate('Updated').''; } - if ( array_key_exists('revokeAllTokens',$_POST) ) { + if ( array_key_exists('revokeAllTokens', $_POST) ) { revokeAllTokens(); } - if ( array_key_exists('updateSelected',$_POST) ) { + if ( array_key_exists('updateSelected', $_POST) ) { updateSelected(); } ?> From 399508b21174dd63f5631f046a68f725f6cdbe47 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Thu, 2 Jan 2020 10:25:48 -0500 Subject: [PATCH 45/71] fix JWT access token always being 1 hr --- web/api/app/Controller/HostController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php index 300352949..7ddba57df 100644 --- a/web/api/app/Controller/HostController.php +++ b/web/api/app/Controller/HostController.php @@ -136,7 +136,7 @@ class HostController extends AppController { }*/ $access_issued_at = time(); - $access_ttl = (ZM_AUTH_HASH_TTL || 2) * 3600; + $access_ttl = max(ZM_AUTH_HASH_TTL,1) * 3600; // by default access token will expire in 2 hrs // you can change it by changing the value of ZM_AUTH_HASH_TLL From 9d57be4c9ec9df7b456ffe05529591b15dc6d5e7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 2 Jan 2020 16:24:43 -0500 Subject: [PATCH 46/71] google code style, remove redundant code matching parent. Don't re-instantiate UA. --- .../lib/ZoneMinder/Control/Amcrest_HTTP.pm | 384 +++++++----------- 1 file changed, 152 insertions(+), 232 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm index e95f86cba..71ea894dc 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm @@ -1,6 +1,6 @@ # ========================================================================== # -# ZoneMinder Acrest HTTP API Control Protocol Module, 20180214, Rev 3.0 +# ZoneMinder Amcrest HTTP API Control Protocol Module, 20180214, Rev 3.0 # # Change Log # @@ -8,7 +8,7 @@ # - Fixes incorrect method names # - Updates control sequences to Amcrest HTTP Protocol API v 2.12 # - Extends control features -# +# # Rev 2.0: # - Fixed installation instructions text, no changes to functionality. # @@ -38,6 +38,7 @@ use Time::HiRes qw( usleep ); require ZoneMinder::Base; require ZoneMinder::Control; +require LWP::UserAgent; our @ISA = qw(ZoneMinder::Control); @@ -50,130 +51,64 @@ our @ISA = qw(ZoneMinder::Control); 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; +sub new { + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new($id); + bless($self, $class); + return $self; } -our $AUTOLOAD; +sub open { + my $self = shift; -sub AUTOLOAD -{ - my $self = shift; - my $class = ref($self) || croak( "$self not object" ); - my $name = $AUTOLOAD; - $name =~ s/.*://; - Debug( "Received command: $name" ); - if ( exists($self->{$name}) ) - { - return( $self->{$name} ); - } - Fatal( "Can't access $name member of object of class $class" ); + $self->loadMonitor(); + my $user; + my $password; + + if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) { + $user = $1; + $password = $2; + $$self{address} = $3; + } + + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->credentials($$self{address}, 'Login to ' . $self->{Monitor}->{ControlDevice}, $user, $password); + $self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION); + $self->{state} = 'open'; } -sub open -{ - my $self = shift; - - $self->loadMonitor(); - $self->{state} = 'open'; +sub close { + my $self = shift; + $self->{state} = 'closed'; } -sub initUA -{ - my $self = shift; - my $user = undef; - my $password = undef; - my $address = undef; +sub sendCmd { + my $self = shift; + my $cmd = shift; + my $result = undef; - if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) - { - $user = $1; - $password = $2; - $address = $3; - } + $self->printMsg($cmd, 'Tx'); - use LWP::UserAgent; - $self->{ua} = LWP::UserAgent->new; - $self->{ua}->credentials("$address", "Login to " . $self->{Monitor}->{ControlDevice}, "$user", "$password"); - $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION ); + my $req = HTTP::Request->new( GET=>"http://$$self{address}/$cmd" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) { + $result = !undef; + # Command to camera appears successful, write Info item to log + Info('Camera control: \''.$res->status_line().'\' for URL '.$self->{Monitor}->{ControlAddress}.'/'.$cmd); + # TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status. + } else { + Error('Camera control command FAILED: \''.$res->status_line().'\' for URL '.$self->{Monitor}->{ControlAddress}.'/'.$cmd); + } + + return $result; } -sub destroyUA -{ - my $self = shift; - - $self->{ua} = undef; -} - -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 -{ - my $self = shift; - my $cmd = shift; - my $result = undef; - - destroyUA($self); - initUA($self); - - my $user = undef; - my $password = undef; - my $address = undef; - - if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) - { - $user = $1; - $password = $2; - $address = $3; - } - - printMsg( $cmd, "Tx" ); - - my $req = HTTP::Request->new( GET=>"http://$address/$cmd" ); - my $res = $self->{ua}->request($req); - - if ( $res->is_success ) - { - $result = !undef; - # Command to camera appears successful, write Info item to log - Info( "Camera control: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" ); - # TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status. - } - else - { - Error( "Camera control command FAILED: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" ); - } - - return( $result ); -} - -sub reset -{ - my $self = shift; - # This reboots the camera effectively resetting it - Debug( "Camera Reset" ); - $self->sendCmd( 'cgi-bin/magicBox.cgi?action=reboot' ); - ##FIXME: Exit is a bad idea as it appears to cause zmc to run away. - #Exit (0); +sub reset { + my $self = shift; + # This reboots the camera effectively resetting it + $self->sendCmd('cgi-bin/magicBox.cgi?action=reboot'); } # NOTE: I'm putting this in, but absolute camera movement does not seem to be well supported in the classic skin ATM. @@ -184,163 +119,148 @@ sub reset sub moveAbs ## Up, Down, Left, Right, etc. ??? Doesn't make sense here... { - my $self = shift; - my $pan_degrees = shift || 0; - my $tilt_degrees = shift || 0; - my $speed = shift || 1; - Debug( "Move ABS" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degrees.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed ); + my $self = shift; + my $pan_degrees = shift || 0; + my $tilt_degrees = shift || 0; + my $speed = shift || 1; + Debug('Move ABS'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degrees.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed); } -sub moveConUp -{ - my $self = shift; - Debug( "Move Up" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0' ); - usleep (500); ##XXX Should this be passed in as a "speed" parameter? - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConUp { + my $self = shift; + Debug('Move Up'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0'); + usleep(500); ##XXX Should this be passed in as a "speed" parameter? + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0'); } -sub moveConDown -{ - my $self = shift; - Debug( "Move Down" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0' ); - usleep (500); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConDown { + my $self = shift; + Debug('Move Down'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0'); + usleep(500); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0'); } -sub moveConLeft -{ - my $self = shift; - Debug( "Move Left" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0' ); - usleep (500); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConLeft { + my $self = shift; + Debug('Move Left'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0'); + usleep(500); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0'); } -sub moveConRight -{ - my $self = shift; - Debug( "Move Right" ); -# $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=270&arg2=5&arg3=0' ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0' ); - usleep (500); - Debug( "Move Right Stop" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConRight { + my $self = shift; + Debug('Move Right'); + # $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=270&arg2=5&arg3=0' ); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0'); + usleep(500); + Debug('Move Right Stop'); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0'); } -sub moveConUpRight -{ - my $self = shift; - Debug( "Move Diagonally Up Right" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0' ); - usleep (500); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConUpRight { + my $self = shift; + Debug('Move Diagonally Up Right'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0'); + usleep(500); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0'); } -sub moveConDownRight -{ - my $self = shift; - Debug( "Move Diagonally Down Right" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0' ); - usleep (500); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConDownRight { + my $self = shift; + Debug('Move Diagonally Down Right'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0'); + usleep(500); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0'); } -sub moveConUpLeft -{ - my $self = shift; - Debug( "Move Diagonally Up Left" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0' ); - usleep (500); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConUpLeft { + my $self = shift; + Debug('Move Diagonally Up Left'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0'); + usleep(500); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0'); } -sub moveConDownLeft -{ - my $self = shift; - Debug( "Move Diagonally Down Left" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0' ); - usleep (500); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0' ); +sub moveConDownLeft { + my $self = shift; + Debug('Move Diagonally Down Left'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0'); + usleep (500); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0'); } # Stop is not "correctly" implemented as control_functions.php translates this to "Center" # So we'll just send the camera to 0* Horz, 0* Vert, zoom out; Also, Amcrest does not seem to # support a generic stop-all-current-action command. -sub moveStop -{ - my $self = shift; - Debug( "Move Stop/Center" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1' ); +sub moveStop { + my $self = shift; + Debug('Move Stop/Center'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1'); } # Move Camera to Home Position # The current API does not support a Home per se, so we'll just send the camera to preset #1 # NOTE: It goes without saying that the user must have set up preset #1 for this to work. -sub presetHome -{ - my $self = shift; - Debug( "Home Preset" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0' ); +sub presetHome { + my $self = shift; + Debug('Home Preset'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0'); } -sub presetGoto -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - Debug( "Go To Preset $preset" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' ); +sub presetGoto { + my $self = shift; + my $params = shift; + my $preset = $self->getParam($params, 'preset'); + Debug("Go To Preset $preset"); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0'); } -sub presetSet -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - Debug( "Set Preset" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' ); +sub presetSet { + my $self = shift; + my $params = shift; + my $preset = $self->getParam($params, 'preset'); + Debug('Set Preset'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0'); } # NOTE: This does not appear to be implemented in the classic skin. But we'll leave it here for later. -sub moveMap -{ - my $self = shift; - my $params = shift; +sub moveMap { + my $self = shift; + my $params = shift; - my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 ); - my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/2 ); - # if the camera is mounted upside down, you may have to inverse these coordinates - # just use 360 minus pan instead of pan, 90 minus tilt instead of tilt - # Convert xcoord into pan position 0 to 359 - my $pan = int(360 * $xcoord / $self->{Monitor}{Width}); - # Convert ycoord into tilt position 0 to 89 - my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height}); - # Now get the following url: - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1'); + my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 ); + my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/2 ); + # if the camera is mounted upside down, you may have to inverse these coordinates + # just use 360 minus pan instead of pan, 90 minus tilt instead of tilt + # Convert xcoord into pan position 0 to 359 + my $pan = int(360 * $xcoord / $self->{Monitor}{Width}); + # Convert ycoord into tilt position 0 to 89 + my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height}); + # Now get the following url: + $self->sendCmd('cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1'); } -sub zoomConTele -{ - my $self = shift; - Debug( "Zoom continuous tele" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' ); - usleep (100000); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' ); +sub zoomConTele { + my $self = shift; + Debug('Zoom continuous tele'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0'); + usleep(100000); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0'); } -sub zoomConWide -{ - my $self = shift; - Debug( "Zoom continuous wide" ); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' ); - usleep (100000); - $self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' ); +sub zoomConWide { + my $self = shift; + Debug('Zoom continuous wide'); + $self->sendCmd('cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0'); + usleep (100000); + $self->sendCmd('cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0'); } 1; @@ -355,7 +275,7 @@ ZoneMinder::Control::Amcrest_HTTP - Amcrest camera control =head1 DESCRIPTION -This module contains the implementation of the Amcrest Camera +This module contains the implementation of the Amcrest Camera controllable SDK API. NOTE: This module implements interaction with the camera in clear text. From 1d24e022bb9877e2cd17fa99adc075a740e36dca Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 2 Jan 2020 16:45:27 -0500 Subject: [PATCH 47/71] Add realm detection --- .../lib/ZoneMinder/Control/Amcrest_HTTP.pm | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm index 71ea894dc..3fd36a0c4 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Amcrest_HTTP.pm @@ -63,18 +63,63 @@ sub open { my $self = shift; $self->loadMonitor(); - my $user; + my $username; my $password; + my $realm = 'Login to ' . $self->{Monitor}->{ControlDevice}; if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) { - $user = $1; + $username = $1; $password = $2; $$self{address} = $3; } $self->{ua} = LWP::UserAgent->new; - $self->{ua}->credentials($$self{address}, 'Login to ' . $self->{Monitor}->{ControlDevice}, $user, $password); + $self->{ua}->credentials($$self{address}, $realm, $username, $password); $self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION); + + # Detect REALM + my $res = $self->{ua}->get($$self{address}.'/cgi-bin/ptz.cgi'); + + if ( $res->is_success ) { + $self->{state} = 'open'; + return; + } + + if ( $res->status_line() eq '401 Unauthorized' ) { + + my $headers = $res->headers(); + foreach my $k ( keys %$headers ) { + Debug("Initial Header $k => $$headers{$k}"); + } + + if ( $$headers{'www-authenticate'} ) { + my ( $auth, $tokens ) = $$headers{'www-authenticate'} =~ /^(\w+)\s+(.*)$/; + if ( $tokens =~ /\w+="([^"]+)"/i ) { + if ( $realm ne $1 ) { + $realm = $1; + Debug("Changing REALM to $realm"); + $self->{ua}->credentials($$self{address}, $realm, $username, $password); + $res = $self->{ua}->get($$self{address}.'/cgi-bin/ptz.cgi'); + if ( $res->is_success() ) { + $self->{state} = 'open'; + return; + } + Error('Authentication still failed after updating REALM' . $res->status_line); + $headers = $res->headers(); + foreach my $k ( keys %$headers ) { + Debug("Initial Header $k => $$headers{$k}"); + } # end foreach + } else { + Error('Authentication failed, not a REALM problem'); + } + } else { + Error('Failed to match realm in tokens'); + } # end if + } else { + Debug('No headers line'); + } # end if headers + } # end if $res->status_line() eq '401 Unauthorized' + $self->{state} = 'open'; } From 06f846c88b2029e5e1b96b58f44f507eb24f55f6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 2 Jan 2020 16:52:09 -0500 Subject: [PATCH 48/71] add php-json to depends --- distros/ubuntu1604/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index 7e57c98a8..1b7b96320 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -74,7 +74,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,libfile-slurp-perl ,mysql-client | mariadb-client | virtual-mysql-client ,perl-modules - ,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc + ,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc, php-json ,policykit-1 ,rsyslog | system-log-daemon ,zip From e9815bf9c7373a4e1744290074ae6ec23a18afe2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 2 Jan 2020 16:54:50 -0500 Subject: [PATCH 49/71] add ZM Namespace to Error calls --- web/includes/config.php.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/includes/config.php.in b/web/includes/config.php.in index ef1bf4a16..909a10e15 100644 --- a/web/includes/config.php.in +++ b/web/includes/config.php.in @@ -179,14 +179,14 @@ if ( ! defined('ZM_SERVER_ID') ) { # Use Server lookup so that it caches $Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_NAME)); if ( !$Server ) { - Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.'); + ZM\Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.'); } else { define('ZM_SERVER_ID', $Server->Id()); } } else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) { $Server = ZM\Server::find_one(array('Name'=>ZM_SERVER_HOST)); if ( ! $Server ) { - Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.'); + ZM\Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.'); } else { define('ZM_SERVER_ID', $Server->Id()); } @@ -199,7 +199,7 @@ function process_configfile($configFile) { if ( is_readable( $configFile ) ) { $configvals = array(); - $cfg = fopen($configFile, 'r') or Error("Could not open config file: $configFile."); + $cfg = fopen($configFile, 'r') or ZM\Error("Could not open config file: $configFile."); while ( !feof($cfg) ) { $str = fgets($cfg, 256); if ( preg_match('/^\s*(#.*)?$/', $str) ) { @@ -207,7 +207,7 @@ function process_configfile($configFile) { } else if ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches )) { $configvals[$matches[1]] = $matches[2]; } else { - Error("Malformed line in config $configFile\n$str"); + ZM\Error("Malformed line in config $configFile\n$str"); } } fclose($cfg); From d42e9beddc934c956c0398b42fcb81866b63d7cf Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 2 Jan 2020 17:03:52 -0500 Subject: [PATCH 50/71] Add warnings when the type of movement is not selected --- web/includes/Control.php | 51 ++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/web/includes/Control.php b/web/includes/Control.php index 39c259092..2121061b1 100644 --- a/web/includes/Control.php +++ b/web/includes/Control.php @@ -128,12 +128,16 @@ class Control extends ZM_Object { $cmds['PresetHome'] = 'presetHome'; if ( $this->CanZoom() ) { - if ( $this->CanZoomCon() ) + if ( $this->CanZoomCon() ) { $cmds['ZoomRoot'] = 'zoomCon'; - elseif ( $this->CanZoomRel() ) + } else if ( $this->CanZoomRel() ) { $cmds['ZoomRoot'] = 'zoomRel'; - elseif ( $this->CanZoomAbs() ) + } else if ( $this->CanZoomAbs() ) { $cmds['ZoomRoot'] = 'zoomAbs'; + } else { + $cmds['ZoomRoot'] = ''; + Error('No zoom type selected. Please select Continuous, Relative, Absolute'); + } $cmds['ZoomTele'] = $cmds['ZoomRoot'].'Tele'; $cmds['ZoomWide'] = $cmds['ZoomRoot'].'Wide'; $cmds['ZoomStop'] = 'zoomStop'; @@ -142,12 +146,16 @@ class Control extends ZM_Object { } if ( $this->CanFocus() ) { - if ( $this->CanFocusCon() ) + if ( $this->CanFocusCon() ) { $cmds['FocusRoot'] = 'focusCon'; - elseif ( $this->CanFocusRel() ) + } else if ( $this->CanFocusRel() ) { $cmds['FocusRoot'] = 'focusRel'; - elseif ( $this->CanFocusAbs() ) + } else if ( $this->CanFocusAbs() ) { $cmds['FocusRoot'] = 'focusAbs'; + } else { + $cmds['FocusRoot'] = ''; + Error('No focus type selected. Please select Continuous, Relative, Absolute'); + } $cmds['FocusFar'] = $cmds['FocusRoot'].'Far'; $cmds['FocusNear'] = $cmds['FocusRoot'].'Near'; $cmds['FocusStop'] = 'focusStop'; @@ -156,12 +164,16 @@ class Control extends ZM_Object { } if ( $this->CanIris() ) { - if ( $this->CanIrisCon() ) + if ( $this->CanIrisCon() ) { $cmds['IrisRoot'] = 'irisCon'; - elseif ( $this->CanIrisRel() ) + } else if ( $this->CanIrisRel() ) { $cmds['IrisRoot'] = 'irisRel'; - elseif ( $this->CanIrisAbs() ) + } else if ( $this->CanIrisAbs() ) { $cmds['IrisRoot'] = 'irisAbs'; + } else { + $cmds['IrisRoot'] = ''; + Error('No iris type selected. Please select Continuous, Relative, Absolute'); + } $cmds['IrisOpen'] = $cmds['IrisRoot'].'Open'; $cmds['IrisClose'] = $cmds['IrisRoot'].'Close'; $cmds['IrisStop'] = 'irisStop'; @@ -170,12 +182,16 @@ class Control extends ZM_Object { } if ( $this->CanWhite() ) { - if ( $this->CanWhiteCon() ) + if ( $this->CanWhiteCon() ) { $cmds['WhiteRoot'] = 'whiteCon'; - elseif ( $this->CanWhiteRel() ) + } else if ( $this->CanWhiteRel() ) { $cmds['WhiteRoot'] = 'whiteRel'; - elseif ( $this->CanWhiteAbs() ) + } else if ( $this->CanWhiteAbs() ) { $cmds['WhiteRoot'] = 'whiteAbs'; + } else { + Error('No White type selected. Please select Continuous, Relative, Absolute'); + $cmds['WhiteRoot'] = ''; + } $cmds['WhiteIn'] = $cmds['WhiteRoot'].'In'; $cmds['WhiteOut'] = $cmds['WhiteRoot'].'Out'; $cmds['WhiteAuto'] = 'whiteAuto'; @@ -183,12 +199,16 @@ class Control extends ZM_Object { } if ( $this->CanGain() ) { - if ( $this->CanGainCon() ) + if ( $this->CanGainCon() ) { $cmds['GainRoot'] = 'gainCon'; - elseif ( $this->CanGainRel() ) + } else if ( $this->CanGainRel() ) { $cmds['GainRoot'] = 'gainRel'; - elseif ( $this->CanGainAbs() ) + } else if ( $this->CanGainAbs() ) { $cmds['GainRoot'] = 'gainAbs'; + } else { + Error('No Gain type selected'); + $cmds['GainRoot'] = ''; + } $cmds['GainUp'] = $cmds['GainRoot'].'Up'; $cmds['GainDown'] = $cmds['GainRoot'].'Down'; $cmds['GainAuto'] = 'gainAuto'; @@ -207,6 +227,7 @@ class Control extends ZM_Object { $cmds['Center'] = $cmds['PresetHome']; } else { $cmds['MoveRoot'] = ''; + Error('No move type selected. Please select Continuous, Relative, Absolute'); } $cmds['MoveUp'] = $cmds['MoveRoot'].'Up'; From 0b3776dbf089466c5f13b8658b2dc2505acf71e5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Jan 2020 15:57:29 -0500 Subject: [PATCH 51/71] change text inputs to number inputs, cleanups --- web/skins/classic/views/controlcap.php | 197 +++++++++++-------------- 1 file changed, 86 insertions(+), 111 deletions(-) diff --git a/web/skins/classic/views/controlcap.php b/web/skins/classic/views/controlcap.php index bc48d05e4..20eb02ca3 100644 --- a/web/skins/classic/views/controlcap.php +++ b/web/skins/classic/views/controlcap.php @@ -18,40 +18,30 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canEdit( 'Control' ) ) -{ - $view = "error"; - return; +if ( !canEdit('Control') ) { + $view = 'error'; + return; } $tabs = array(); -$tabs["main"] = translate('Main'); -$tabs["move"] = translate('Move'); -$tabs["pan"] = translate('Pan'); -$tabs["tilt"] = translate('Tilt'); -$tabs["zoom"] = translate('Zoom'); -$tabs["focus"] = translate('Focus'); -$tabs["white"] = translate('White'); -$tabs["iris"] = translate('Iris'); -$tabs["presets"] = translate('Presets'); +$tabs['main'] = translate('Main'); +$tabs['move'] = translate('Move'); +$tabs['pan'] = translate('Pan'); +$tabs['tilt'] = translate('Tilt'); +$tabs['zoom'] = translate('Zoom'); +$tabs['focus'] = translate('Focus'); +$tabs['white'] = translate('White'); +$tabs['iris'] = translate('Iris'); +$tabs['presets'] = translate('Presets'); -if ( isset($_REQUEST['tab']) ) - $tab = validHtmlStr($_REQUEST['tab']); -else - $tab = "main"; +$tab = isset($_REQUEST['tab']) ? validHtmlStr($_REQUEST['tab']) :'main'; -if ( isset( $_REQUEST['newControl'] ) ) -{ +if ( isset($_REQUEST['newControl']) ) { $newControl = $_REQUEST['newControl']; -} -else -{ - if ( !empty($_REQUEST['cid']) ) - { - $control = dbFetchOne( 'SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid'] ) ); - } - else - { +} else { + if ( !empty($_REQUEST['cid']) ) { + $control = dbFetchOne('SELECT * FROM Controls WHERE Id = ?', NULL, array($_REQUEST['cid'])); + } else { $control = array( 'Name' => translate('New'), 'Type' => "Local", @@ -166,16 +156,12 @@ xhtmlHeaders(__FILE__, translate('ControlCap')." - ".$newControl['Name'] );
    $value ) -{ - if ( $tab == $name ) - { +foreach ( $tabs as $name=>$value ) { + if ( $tab == $name ) { ?>
  • $value ) @@ -201,8 +186,7 @@ if ( $tab != 'main' ) @@ -212,8 +196,7 @@ if ( $tab != 'move' ) @@ -227,8 +210,7 @@ if ( $tab != 'pan' ) @@ -242,8 +224,7 @@ if ( $tab != 'tilt' ) @@ -258,8 +239,7 @@ if ( $tab != 'zoom' ) @@ -275,8 +255,7 @@ if ( $tab != 'focus' ) @@ -292,8 +271,7 @@ if ( $tab != 'iris' ) @@ -309,8 +287,7 @@ if ( $tab != 'gain' ) @@ -326,8 +303,7 @@ if ( $tab != 'white' ) @@ -336,19 +312,17 @@ if ( $tab != 'presets' ) - +
    - -translate('Local'), 'Remote'=>translate('Remote'), 'Ffmpeg'=>translate('Ffmpeg'), 'Libvlc'=>translate('Libvlc'), 'cURL'=>"cURL"); -?> - + + @@ -373,15 +347,15 @@ switch ( $tab ) { ?> - - - - + + + + - - + + - + - - - - + + + + - - + + - + - - - - + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - +
    translate('Local'), 'Remote'=>translate('Remote'), 'Ffmpeg'=>translate('Ffmpeg'), 'Libvlc'=>translate('Libvlc'), 'cURL'=>'cURL'); + echo buildSelect('newControl[Type]', $types); ?>
    checked="checked"/>
    checked="checked"/>
    checked="checked">
    checked="checked"/>
    checked="checked"/>
    checked="checked">
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    checked="checked"/>
    - disabled="disabled"/> + +
From c4aaa33beaa0a29be4df6c89b6b6eac76923eb6c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Jan 2020 15:57:51 -0500 Subject: [PATCH 52/71] add widths for number inputs on controlcap view --- web/skins/classic/css/base/views/controlcap.css | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 web/skins/classic/css/base/views/controlcap.css diff --git a/web/skins/classic/css/base/views/controlcap.css b/web/skins/classic/css/base/views/controlcap.css new file mode 100644 index 000000000..ed9a664e7 --- /dev/null +++ b/web/skins/classic/css/base/views/controlcap.css @@ -0,0 +1,4 @@ + +input[type="number"] { + width: 70px; +} From 158e26bb2594a576089421fc260b390c08a0b2c2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Jan 2020 15:58:02 -0500 Subject: [PATCH 53/71] split long lines --- web/skins/classic/css/base/views/controlcaps.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/css/base/views/controlcaps.css b/web/skins/classic/css/base/views/controlcaps.css index 1a2783fd7..d860d88ae 100644 --- a/web/skins/classic/css/base/views/controlcaps.css +++ b/web/skins/classic/css/base/views/controlcaps.css @@ -1,3 +1,9 @@ -#content table.major .colCanMove, #content table.major .colCanZoom, #content table.major .colCanFocus, #content table.major .colCanIris, #content table.major .colCanWhiteBal, #content table.major .colHasPresets { +#content table.major .colCanMove, +#content table.major .colCanZoom, +#content table.major .colCanFocus, +#content table.major .colCanIris, +#content table.major .colCanWhiteBal, +#content table.major .colHasPresets { text-align: center; } + From f572c4092a5ee20bc43756ba2422853bd7b75a67 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Jan 2020 15:58:57 -0500 Subject: [PATCH 54/71] add checks for Zoom, Focus, White, Iris movement types --- web/skins/classic/views/js/controlcap.js | 124 +++++++++++++++++++++-- 1 file changed, 117 insertions(+), 7 deletions(-) diff --git a/web/skins/classic/views/js/controlcap.js b/web/skins/classic/views/js/controlcap.js index c52ab3dd5..a94f14acd 100644 --- a/web/skins/classic/views/js/controlcap.js +++ b/web/skins/classic/views/js/controlcap.js @@ -3,21 +3,131 @@ function validateForm( form ) { // If "Can Move" is enabled, then the end user must also select at least one of the other check boxes (excluding Can Move Diagonally) if ( form.elements['newControl[CanMove]'].checked ) { - if ( !(form.elements['newControl[CanMoveCon]'].checked || form.elements['newControl[CanMoveRel]'].checked || form.elements['newControl[CanMoveAbs]'].checked || form.elements['newControl[CanMoveMap]'].checked) ) { - errors[errors.length] = "In addition to \"Can Move\", you also must select at least one of: \"Can Move Mapped\", \"Can Move Absolute\", \"Can Move Relative\", or \"Can Move Continuous\""; + if ( !( + form.elements['newControl[CanMoveCon]'].checked + || + form.elements['newControl[CanMoveRel]'].checked + || + form.elements['newControl[CanMoveAbs]'].checked + || + form.elements['newControl[CanMoveMap]'].checked + ) ) { + errors[errors.length] = 'In addition to "Can Move", you also must select at least one of: "Can Move Mapped", "Can Move Absolute", "Can Move Relative", or "Can Move Continuous"'; } } else { // Now lets check for the opposite condition. If any of the boxes below Can Move are checked, but Can Move is not checked then signal an error - if ( form.elements['newControl[CanMoveCon]'].checked || form.elements['newControl[CanMoveRel]'].checked || form.elements['newControl[CanMoveAbs]'].checked || form.elements['newControl[CanMoveMap]'].checked || form.elements['newControl[CanMoveDiag]'].checked ) { - errors[errors.length] = "\"Can Move\" must also be selected if any one of the movement types are sleceted"; + if ( form.elements['newControl[CanMoveCon]'].checked + || + form.elements['newControl[CanMoveRel]'].checked + || + form.elements['newControl[CanMoveAbs]'].checked + || + form.elements['newControl[CanMoveMap]'].checked + || + form.elements['newControl[CanMoveDiag]'].checked + ) { + errors[errors.length] = '"Can Move" must also be selected if any one of the movement types are selected.'; + } + } + // If "Can Zoom" is enabled, then the end user must also select at least one of the other check boxes + if ( form.elements['newControl[CanZoom]'].checked ) { + if ( !( + form.elements['newControl[CanZoomCon]'].checked + || + form.elements['newControl[CanZoomRel]'].checked + || + form.elements['newControl[CanZoomAbs]'].checked + ) ) { + errors[errors.length] = 'In addition to "Can Zoom", you also must select at least one of: "Can Zoom Absolute", "Can Zoom Relative", or "Can Zoom Continuous"'; + } + } else { + // Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error + + if ( form.elements['newControl[CanZoomCon]'].checked + || + form.elements['newControl[CanZoomRel]'].checked + || + form.elements['newControl[CanZoomAbs]'].checked + ) { + errors[errors.length] = '"Can Move" must also be selected if any one of the zoom types are selected.'; + } + } + // If "Can Zoom" is enabled, then the end user must also select at least one of the other check boxes + if ( form.elements['newControl[CanFocus]'].checked ) { + if ( !( + form.elements['newControl[CanFocusCon]'].checked + || + form.elements['newControl[CanFocusRel]'].checked + || + form.elements['newControl[CanFocusAbs]'].checked + ) ) { + errors[errors.length] = 'In addition to "Can Focus", you also must select at least one of: "Can Focus Absolute", "Can Focus Relative", or "Can Focus Continuous"'; + } + } else { + // Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error + + if ( form.elements['newControl[CanFocusCon]'].checked + || + form.elements['newControl[CanFocusRel]'].checked + || + form.elements['newControl[CanFocusAbs]'].checked + ) { + errors[errors.length] = '"Can Focus" must also be selected if any one of the focus types are selected.'; + } + } + // If "Can White" is enabled, then the end user must also select at least one of the other check boxes + if ( form.elements['newControl[CanWhite]'].checked ) { + if ( !( + form.elements['newControl[CanWhiteCon]'].checked + || + form.elements['newControl[CanWhiteRel]'].checked + || + form.elements['newControl[CanWhiteAbs]'].checked + ) ) { + errors[errors.length] = 'In addition to "Can White Balance", you also must select at least one of: "Can White Bal Absolute", "Can White Bal Relative", or "Can White Bal Continuous"'; + } + } else { + // Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error + + if ( form.elements['newControl[CanWhiteCon]'].checked + || + form.elements['newControl[CanWhiteRel]'].checked + || + form.elements['newControl[CanWhiteAbs]'].checked + ) { + errors[errors.length] = '"Can White Balance" must also be selected if any one of the white balance types are selected.'; + } + } + + // If "Can Iris" is enabled, then the end user must also select at least one of the other check boxes + if ( form.elements['newControl[CanIris]'].checked ) { + if ( !( + form.elements['newControl[CanIrisCon]'].checked + || + form.elements['newControl[CanIrisRel]'].checked + || + form.elements['newControl[CanIrisAbs]'].checked + ) ) { + errors[errors.length] = 'In addition to "Can Iris", you also must select at least one of: "Can Iris Absolute", "Can Iris Relative", or "Can Iris Continuous"'; + } + } else { + // Now lets check for the opposite condition. If any of the boxes below Can Zoom are checked, but Can Zoom is not checked then signal an error + + if ( form.elements['newControl[CanIrisCon]'].checked + || + form.elements['newControl[CanIrisRel]'].checked + || + form.elements['newControl[CanIrisAbs]'].checked + ) { + errors[errors.length] = '"Can Iris" must also be selected if any one of the iris types are selected.'; } } if ( errors.length ) { - alert( errors.join( "\n" ) ); - return ( false ); + alert(errors.join("\n")); + return false; } - return ( true ); + return true; } From 0a495395b06b2ddd3471b2841055f91db23b237b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Jan 2020 16:34:46 -0500 Subject: [PATCH 55/71] Restore Gain tab --- web/skins/classic/views/controlcap.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/controlcap.php b/web/skins/classic/views/controlcap.php index 20eb02ca3..68ab25b60 100644 --- a/web/skins/classic/views/controlcap.php +++ b/web/skins/classic/views/controlcap.php @@ -30,6 +30,7 @@ $tabs['pan'] = translate('Pan'); $tabs['tilt'] = translate('Tilt'); $tabs['zoom'] = translate('Zoom'); $tabs['focus'] = translate('Focus'); +$tabs['gain'] = translate('Gain'); $tabs['white'] = translate('White'); $tabs['iris'] = translate('Iris'); $tabs['presets'] = translate('Presets'); From e951b0af1cb097dc58d322c19b45680a07b39bbc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Jan 2020 16:35:04 -0500 Subject: [PATCH 56/71] add code to set default value for checkboxes --- web/includes/actions/controlcap.php | 59 +++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/web/includes/actions/controlcap.php b/web/includes/actions/controlcap.php index eec3ffd8b..ad4985f11 100644 --- a/web/includes/actions/controlcap.php +++ b/web/includes/actions/controlcap.php @@ -28,6 +28,65 @@ if ( $action == 'controlcap' ) { require_once('includes/Control.php'); $Control = new ZM\Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null ); + $field_defaults = array( + 'CanWake' => 0, + 'CanSleep' => 0, + 'CanReset' => 0, + 'CanReboot' => 0, + 'CanMove' => 0, + 'CanMoveDiag' => 0, + 'CanMoveMap' => 0, + 'CanMoveRel' => 0, + 'CanMoveAbs' => 0, + 'CanMoveCon' => 0, + 'CanPan' => 0, + 'HasPanSpeed' => 0, + 'HasTurboPan' => 0, + 'CanTilt' => 0, + 'HasTiltSpeed' => 0, + 'HasTurboTilt' => 0, + 'CanZoom' => 0, + 'CanZoomRel' => 0, + 'CanZoomAbs' => 0, + 'CanZoomCon' => 0, + 'HasZoomSpeed' => 0, + 'CanFocus' => 0, + 'CanAutoFocus' => 0, + 'CanFocusRel' => 0, + 'CanFocusAbs' => 0, + 'CanFocusCon' => 0, + 'HasFocusSpeed' => 0, + 'CanGain' => 0, + 'CanAutoGain' => 0, + 'CanGainRel' => 0, + 'CanGainAbs' => 0, + 'CanGainCon' => 0, + 'HasGainSpeed' => 0, + 'CanWhite' => 0, + 'CanAutoWhite' => 0, + 'CanWhiteRel' => 0, + 'CanWhiteAbs' => 0, + 'CanWhiteCon' => 0, + 'HasWhiteSpeed' => 0, + 'CanIris' => 0, + 'CanAutoIris' => 0, + 'CanIrisRel' => 0, + 'CanIrisAbs' => 0, + 'CanIrisCon' => 0, + 'HasIrisSpeed' => 0, + 'HasPresets' => 0, + 'HasHomePreset' => 0, + 'CanSetPresets' => 0, + ); + + # Checkboxes don't return an element in the POST data, so won't be present in newControl. + # So force a value for these fields + foreach ( $field_defaults as $field => $value ) { + if ( ! (isset($_REQUEST['newControl'][$field]) and $_REQUEST['newControl'][$field]) ) { + $_REQUEST['newControl'][$field] = $value; + } + } # end foreach type + //$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns ); $Control->save($_REQUEST['newControl']); $refreshParent = true; From 7fdf6165d52c2f4ccf5a3ede3c9bd62fa4501d22 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 3 Jan 2020 17:08:11 -0500 Subject: [PATCH 57/71] Fix case in var name --- web/skins/classic/views/js/montagereview.js.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php index ecea1ba6f..526ce0bb5 100644 --- a/web/skins/classic/views/js/montagereview.js.php +++ b/web/skins/classic/views/js/montagereview.js.php @@ -18,7 +18,7 @@ var speedIndex=; // for history, and fps for live, and dynamically determined (in ms) var currentDisplayInterval=; -var playSecsperInterval=1; // How many seconds of recorded image we play per refresh determined by speed (replay rate) and display interval; (default=1 if coming from live) +var playSecsPerInterval=1; // How many seconds of recorded image we play per refresh determined by speed (replay rate) and display interval; (default=1 if coming from live) var timerInterval; // milliseconds between interrupts var timerObj; // object to hold timer interval; var freeTimeLastIntervals=[]; // Percentage of current interval used in loading most recent image From 0fb806d9d750c0a6aa9767439f23dd52b30a091e Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 4 Jan 2020 15:30:32 -0600 Subject: [PATCH 58/71] Allow aarch64 as a valid build architecture --- utils/packpack/startpackpack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index e6b68f66d..4af3cc161 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -30,7 +30,7 @@ checksanity () { ARCH="x86_64" fi - if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" ]]; then + if [[ "${ARCH}" != "x86_64" && "${ARCH}" != "i386" && "${ARCH}" != "armhf" && "${ARCH}" != "aarch64" ]]; then echo echo "ERROR: Unsupported architecture specified \"${ARCH}\"." echo From 00f8a450dee9928bf3a71a460bb67b3fe56553f5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 5 Jan 2020 14:59:25 -0500 Subject: [PATCH 59/71] spaces and quotes --- web/skins/classic/views/js/event.js | 157 ++++++++++++++-------------- 1 file changed, 79 insertions(+), 78 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 76fc47c79..f7da1341a 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -57,7 +57,7 @@ function setAlarmCues(data) { function renderAlarmCues(containerEl) { if ( !( cueFrames && cueFrames.length ) ) { - console.log("No cue frames for event"); + console.log('No cue frames for event'); return; } // This uses the Delta of the last frame to get the length of the event. I can't help but wonder though @@ -139,7 +139,7 @@ function setButtonState( element, butClass ) { element.disabled = false; } } else { - console.log("Element was null in setButtonState"); + console.log('Element was null in setButtonState'); } } @@ -211,7 +211,7 @@ var lastEventId = 0; var zmsBroke = false; //Use alternate navigation if zms has crashed function getCmdResponse( respObj, respText ) { - if ( checkStreamForErrors("getCmdResponse", respObj) ) { + if ( checkStreamForErrors('getCmdResponse', respObj) ) { console.log('Got an error from getCmdResponse'); console.log(respObj); console.log(respText); @@ -541,9 +541,9 @@ var scroll = null; var currEventId = null; var CurEventDefVideoPath = null; -function getEventResponse( respObj, respText ) { - if ( checkStreamForErrors( "getEventResponse", respObj ) ) { - console.log("getEventResponse: errors" ); +function getEventResponse(respObj, respText) { + if ( checkStreamForErrors('getEventResponse', respObj) ) { + console.log('getEventResponse: errors'); return; } @@ -582,7 +582,7 @@ function getEventResponse( respObj, respText ) { //eventImg.setStyles( { 'width': eventData.width, 'height': eventData.height } ); if ( vid && CurEventDefVideoPath ) { vid.src({type: 'video/mp4', src: CurEventDefVideoPath}); //Currently mp4 is all we use - console.log("getEventResponse"); + console.log('getEventResponse'); initialAlarmCues(eventData.Id);//ajax and render, new event addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartTime); CurEventDefVideoPath = null; @@ -644,7 +644,7 @@ var frameBatch = 40; function loadEventThumb( event, frame, loadImage ) { var thumbImg = $('eventThumb'+frame.FrameId); if ( !thumbImg ) { - console.error( "No holder found for frame "+frame.FrameId ); + console.error('No holder found for frame '+frame.FrameId); return; } var img = new Asset.image( imagePrefix+frame.EventId+"&fid="+frame.FrameId, @@ -666,31 +666,31 @@ function loadEventThumb( event, frame, loadImage ) { ); } -function loadEventImage( event, frame ) { - console.debug( "Loading "+event.Id+"/"+frame.FrameId ); +function loadEventImage(event, frame) { + console.debug('Loading '+event.Id+'/'+frame.FrameId); var eventImg = $('eventImage'); var thumbImg = $('eventThumb'+frame.FrameId); - if ( eventImg.getProperty( 'src' ) != thumbImg.getProperty( 'src' ) ) { + if ( eventImg.getProperty('src') != thumbImg.getProperty('src') ) { var eventImagePanel = $('eventImagePanel'); - if ( eventImagePanel.getStyle( 'display' ) != 'none' ) { - var lastThumbImg = $('eventThumb'+eventImg.getProperty( 'alt' )); + if ( eventImagePanel.getStyle('display') != 'none' ) { + var lastThumbImg = $('eventThumb'+eventImg.getProperty('alt')); lastThumbImg.removeClass('selected'); - lastThumbImg.setOpacity( 1.0 ); + lastThumbImg.setOpacity(1.0); } - $('eventImageBar').setStyle( 'width', event.Width ); - if ( frame.Type=='Alarm' ) { - $('eventImageStats').removeClass( 'hidden' ); + $('eventImageBar').setStyle('width', event.Width); + if ( frame.Type == 'Alarm' ) { + $('eventImageStats').removeClass('hidden'); } else { - $('eventImageStats').addClass( 'hidden' ); + $('eventImageStats').addClass('hidden'); } - thumbImg.addClass( 'selected' ); - thumbImg.setOpacity( 0.5 ); + thumbImg.addClass('selected'); + thumbImg.setOpacity(0.5); - if ( eventImagePanel.getStyle( 'display' ) == 'none' ) { - eventImagePanel.setOpacity( 0 ); - eventImagePanel.setStyle( 'display', 'inline-block' ); + if ( eventImagePanel.getStyle('display') == 'none' ) { + eventImagePanel.setOpacity(0); + eventImagePanel.setStyle('display', 'inline-block'); new Fx.Tween( eventImagePanel, {duration: 500, transition: Fx.Transitions.Sine} ).start( 'opacity', 0, 1 ); } @@ -702,29 +702,29 @@ function loadEventImage( event, frame ) { 'height': $j('#eventThumbs').height() - $j('#eventImageBar').outerHeight(true)-10 } ); - $('eventImageNo').set( 'text', frame.FrameId ); + $('eventImageNo').set('text', frame.FrameId); $('prevImageBtn').disabled = (frame.FrameId==1); $('nextImageBtn').disabled = (frame.FrameId==event.Frames); } } function hideEventImageComplete() { - var thumbImg = $('eventThumb'+$('eventImage').getProperty( 'alt' )); + var thumbImg = $('eventThumb'+$('eventImage').getProperty('alt')); if ( thumbImg ) { thumbImg.removeClass('selected'); - thumbImg.setOpacity( 1.0 ); + thumbImg.setOpacity(1.0); } else { - console.log("Unable to find eventThumb at " + 'eventThumb'+$('eventImage').getProperty( 'alt' ) ); + console.log('Unable to find eventThumb at eventThumb'+$('eventImage').getProperty('alt')); } $('prevImageBtn').disabled = true; $('nextImageBtn').disabled = true; - $('eventImagePanel').setStyle( 'display', 'none' ); - $('eventImageStats').addClass( 'hidden' ); + $('eventImagePanel').setStyle('display', 'none'); + $('eventImageStats').addClass('hidden'); } function hideEventImage() { - if ( $('eventImagePanel').getStyle( 'display' ) != 'none' ) { - new Fx.Tween( $('eventImagePanel'), {duration: 500, transition: Fx.Transitions.Sine, onComplete: hideEventImageComplete} ).start( 'opacity', 1, 0 ); + if ( $('eventImagePanel').getStyle('display') != 'none' ) { + new Fx.Tween( $('eventImagePanel'), {duration: 500, transition: Fx.Transitions.Sine, onComplete: hideEventImageComplete} ).start('opacity', 1, 0); } } @@ -751,15 +751,15 @@ function resetEventStills() { } } -function getFrameResponse( respObj, respText ) { - if ( checkStreamForErrors( "getFrameResponse", respObj ) ) { +function getFrameResponse(respObj, respText) { + if ( checkStreamForErrors('getFrameResponse', respObj) ) { return; } var frame = respObj.frameimage; if ( !eventData ) { - console.error( "No event "+frame.EventId+" found" ); + console.error('No event '+frame.EventId+' found'); return; } @@ -769,21 +769,21 @@ function getFrameResponse( respObj, respText ) { eventData['frames'][frame.FrameId] = frame; - loadEventThumb( eventData, frame, respObj.loopback=="true" ); + loadEventThumb(eventData, frame, respObj.loopback=="true"); } var frameReq = new Request.JSON( {url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getFrameResponse} ); function frameQuery( eventId, frameId, loadImage ) { var parms = "view=request&request=status&entity=frameimage&id[0]="+eventId+"&id[1]="+frameId+"&loopback="+loadImage; - frameReq.send( parms ); + frameReq.send(parms); } var currFrameId = null; function checkFrames( eventId, frameId, loadImage ) { if ( !eventData ) { - console.error( "No event "+eventId+" found" ); + console.error("No event "+eventId+" found"); return; } @@ -804,29 +804,30 @@ function checkFrames( eventId, frameId, loadImage ) { for ( var fid = loFid; fid <= hiFid; fid++ ) { if ( !$('eventThumb'+fid) ) { - var img = new Element( 'img', {'id': 'eventThumb'+fid, 'src': 'graphics/transparent.png', 'alt': fid, 'class': 'placeholder'} ); - img.addEvent( 'click', function() { - eventData['frames'][fid] = null; checkFrames( eventId, fid ); - } ); - frameQuery( eventId, fid, loadImage && (fid == frameId) ); - var imgs = $('eventThumbs').getElements( 'img' ); + var img = new Element('img', {'id': 'eventThumb'+fid, 'src': 'graphics/transparent.png', 'alt': fid, 'class': 'placeholder'}); + img.addEvent('click', function() { + eventData['frames'][fid] = null; + checkFrames(eventId, fid); + }); + frameQuery(eventId, fid, loadImage && (fid == frameId)); + var imgs = $('eventThumbs').getElements('img'); var injected = false; if ( fid < imgs.length ) { - img.inject( imgs[fid-1], 'before' ); + img.inject(imgs[fid-1], 'before'); injected = true; } else { injected = imgs.some( function( thumbImg, index ) { - if ( parseInt(img.getProperty( 'alt' )) < parseInt(thumbImg.getProperty( 'alt' )) ) { - img.inject( thumbImg, 'before' ); - return ( true ); + if ( parseInt(img.getProperty('alt')) < parseInt(thumbImg.getProperty('alt')) ) { + img.inject(thumbImg, 'before'); + return true; } - return ( false ); + return false; } ); } if ( !injected ) { - img.inject( $('eventThumbs') ); + img.inject($('eventThumbs')); } var scale = parseInt(img.getStyle('height')); img.setStyles( { @@ -923,7 +924,7 @@ function deleteEvent() { getActResponse(respObj, respText); // We must wait for the deletion to happen before navigating to the next // event or this request will be cancelled. - streamNext( true ); + streamNext(true); }, }); deleteReq.send("view=request&request=event&id="+eventData.Id+"&action=delete"); @@ -931,43 +932,43 @@ function deleteEvent() { function renameEvent() { var newName = $('eventName').get('value'); - actQuery( 'rename', {eventName: newName} ); + actQuery('rename', {eventName: newName}); } function editEvent() { - createPopup( '?view=eventdetail&eid='+eventData.Id, 'zmEventDetail', 'eventdetail' ); + createPopup('?view=eventdetail&eid='+eventData.Id, 'zmEventDetail', 'eventdetail'); } function exportEvent() { - createPopup( '?view=export&eid='+eventData.Id, 'zmExport', 'export' ); + createPopup('?view=export&eid='+eventData.Id, 'zmExport', 'export'); } function archiveEvent() { - actQuery( 'archive' ); + actQuery('archive'); } function unarchiveEvent() { - actQuery( 'unarchive' ); + actQuery('unarchive'); } function showEventFrames() { - createPopup( '?view=frames&eid='+eventData.Id, 'zmFrames', 'frames', WEB_LIST_THUMB_WIDTH, WEB_LIST_THUMB_HEIGHT ); + createPopup('?view=frames&eid='+eventData.Id, 'zmFrames', 'frames', WEB_LIST_THUMB_WIDTH, WEB_LIST_THUMB_HEIGHT); } function showStream() { - $('eventStills').addClass( 'hidden' ); - $('eventVideo').removeClass( 'hidden' ); + $('eventStills').addClass('hidden'); + $('eventVideo').removeClass('hidden'); - $('stillsEvent').removeClass( 'hidden' ); - $('streamEvent').addClass( 'hidden' ); + $('stillsEvent').removeClass('hidden'); + $('streamEvent').addClass('hidden'); streamMode = 'video'; if (scale == 'auto') changeScale(); } function showStills() { - $('eventStills').removeClass( 'hidden' ); - $('eventVideo').addClass( 'hidden' ); + $('eventStills').removeClass('hidden'); + $('eventVideo').addClass('hidden'); if (vid && ( vid.paused != true ) ) { // Pause the video @@ -978,14 +979,14 @@ function showStills() { //playButton.innerHTML = "Play"; } - $('stillsEvent').addClass( 'hidden' ); - $('streamEvent').removeClass( 'hidden' ); + $('stillsEvent').addClass('hidden'); + $('streamEvent').removeClass('hidden'); streamMode = 'stills'; pauseClicked(); if ( !scroll ) { - scroll = new Fx.Scroll( 'eventThumbs', { + scroll = new Fx.Scroll('eventThumbs', { wait: false, duration: 500, offset: {'x': 0, 'y': 0}, @@ -999,17 +1000,17 @@ function showStills() { function showFrameStats() { var fid = $('eventImageNo').get('text'); - createPopup( '?view=stats&eid='+eventData.Id+'&fid='+fid, 'zmStats', 'stats', eventData.Width, eventData.Height ); + createPopup('?view=stats&eid='+eventData.Id+'&fid='+fid, 'zmStats', 'stats', eventData.Width, eventData.Height); } function videoEvent() { - createPopup( '?view=video&eid='+eventData.Id, 'zmVideo', 'video', eventData.Width, eventData.Height ); + createPopup('?view=video&eid='+eventData.Id, 'zmVideo', 'video', eventData.Width, eventData.Height); } // Called on each event load because each event can be a different width function drawProgressBar() { var barWidth = $j('#evtStream').width(); - $j('#progressBar').css( 'width', barWidth ); + $j('#progressBar').css('width', barWidth); } // Shows current stream progress. @@ -1032,8 +1033,8 @@ function progressBarNav() { function handleClick( event ) { var target = event.target; - if (vid) { - if (target.id != 'videoobj') return; //ignore clicks on control bar + if ( vid ) { + if (target.id != 'videoobj') return; // ignore clicks on control bar var x = event.offsetX; var y = event.offsetY; } else { @@ -1041,9 +1042,9 @@ function handleClick( event ) { var y = event.page.y - $(target).getTop(); } - if (event.shift || event.shiftKey) {//handle both jquery and mootools + if ( event.shift || event.shiftKey ) { // handle both jquery and mootools streamPan(x, y); - } else if (vid && event.ctrlKey) { //allow zoom out by control click. useful in fullscreen + } else if ( vid && event.ctrlKey ) { // allow zoom out by control click. useful in fullscreen vjsPanZoom('zoomOut', x, y); } else { streamZoomIn(x, y); @@ -1072,7 +1073,7 @@ function initPage() { } } else { progressBarNav(); - streamCmdTimer = streamQuery.delay( 250 ); + streamCmdTimer = streamQuery.delay(250); if ( canStreamNative ) { var imageFeed = $('imageFeed'); if ( !imageFeed ) { @@ -1082,16 +1083,16 @@ function initPage() { if ( !streamImg ) { streamImg = imageFeed.getElement('object'); } - $(streamImg).addEvent( 'click', function( event ) { - handleClick( event ); - } ); + $(streamImg).addEvent('click', function(event) { + handleClick(event); + }); } } } nearEventsQuery(eventData.Id); initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues - if (scale == "auto") changeScale(); + if ( scale == 'auto' ) changeScale(); } // Kick everything off -window.addEventListener( 'DOMContentLoaded', initPage ); +window.addEventListener('DOMContentLoaded', initPage); From 2956e5e156a2d69451d78deb9f553bae674eae59 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 5 Jan 2020 14:30:33 -0600 Subject: [PATCH 60/71] use dnf rather than yum for newer redhat distros --- utils/packpack/startpackpack.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 4af3cc161..6a51e2995 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -9,7 +9,7 @@ # General sanity checks checksanity () { # Check to see if this script has access to all the commands it needs - for CMD in set echo curl git ln mkdir rmdir cat patch; do + for CMD in set echo curl git ln mkdir rmdir cat patch sed; do type $CMD 2>&1 > /dev/null if [ $? -ne 0 ]; then @@ -298,6 +298,11 @@ if [ "${OS}" == "el" ] || [ "${OS}" == "fedora" ]; then commonprep echo "Begin Redhat build..." + # Newer Redhat distros use dnf package manager rather than yum + if [ "${DIST}" -gt "7" ]; then + sed -i 's\yum\dnf\' utils/packpack/redhat_package.mk + fi + setrpmpkgname ln -sfT distros/redhat rpm From 05ac82b0bb5c8494414d342dc903392915ab4e22 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 5 Jan 2020 17:27:45 -0500 Subject: [PATCH 61/71] Handle failure to init hwdevice when trying to use hwaccel. --- src/zm_ffmpeg_camera.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index ef4dfc057..c9dec7e05 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -517,17 +517,17 @@ int FfmpegCamera::OpenFfmpeg() { Debug(1, "Selected hw_pix_fmt %d %s", hw_pix_fmt, av_get_pix_fmt_name(hw_pix_fmt)); - mVideoCodecContext->get_format = get_hw_format; - ret = av_hwdevice_ctx_create(&hw_device_ctx, type, (hwaccel_device != "" ? hwaccel_device.c_str(): NULL), NULL, 0); if ( ret < 0 ) { Error("Failed to create hwaccel device."); - return -1; + hw_pix_fmt = AV_PIX_FMT_NONE; + } else { + Debug(1, "Created hwdevice for %s", hwaccel_device.c_str()); + mVideoCodecContext->get_format = get_hw_format; + mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx); + hwFrame = zm_av_frame_alloc(); } - Debug(1, "Created hwdevice for %s", hwaccel_device.c_str()); - mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx); - hwFrame = zm_av_frame_alloc(); } else { Debug(1, "Failed to setup hwaccel."); } @@ -537,7 +537,7 @@ int FfmpegCamera::OpenFfmpeg() { #else Warning("HWAccel support not compiled in."); #endif - } // end if hwacel_name + } // end if hwaccel_name // Open the codec #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) From c3641df531dbb6e3fc054c3e7873c4ad564ecb91 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 5 Jan 2020 17:30:06 -0500 Subject: [PATCH 62/71] spaces --- web/includes/Monitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 4575d2ab6..b725963f2 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -510,7 +510,7 @@ class Monitor extends ZM_Object { if ( @socket_connect($socket, $sockFile) ) { if ( !socket_write($socket, $optionString) ) { Error('Can\'t write to control socket: '.socket_strerror(socket_last_error($socket))); - return false; + return false; } } else if ( $command != 'quit' ) { $command = ZM_PATH_BIN.'/zmcontrol.pl '.$command.' --id='.$this->{'Id'}; @@ -544,7 +544,7 @@ class Monitor extends ZM_Object { } } catch ( Exception $e ) { Error("Except $e thrown trying to restart zma"); - return false; + return false; } } else { Error('Server not assigned to Monitor in a multi-server setup. Please assign a server to the Monitor.'); From 6ac26ec1aa73bf4ee1af040b1f12dabe7fb5a299 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 5 Jan 2020 17:33:53 -0500 Subject: [PATCH 63/71] quotes --- web/skins/classic/views/js/watch.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index b6127a68d..c151ba3ec 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -44,17 +44,17 @@ function changeScale() { newHeight = monitorHeight * scale / SCALE_BASE; } - Cookie.write( 'zmWatchScale'+monitorId, scale, {duration: 10*365} ); + Cookie.write('zmWatchScale'+monitorId, scale, {duration: 10*365}); /*Stream could be an applet so can't use moo tools*/ var streamImg = $('liveStream'+monitorId); if ( streamImg ) { - streamImg.style.width = newWidth + "px"; - streamImg.style.height = newHeight + "px"; + streamImg.style.width = newWidth + 'px'; + streamImg.style.height = newHeight + 'px'; streamImg.src = streamImg.src.replace(/scale=\d+/i, 'scale='+(scale== 'auto' ? autoScale : scale)); } else { - console.error("No element found for liveStream."); + console.error('No element found for liveStream.'); } } @@ -64,17 +64,17 @@ var lastAlarmState = STATE_IDLE; function setAlarmState( currentAlarmState ) { alarmState = currentAlarmState; - var stateClass = ""; + var stateClass = ''; if ( alarmState == STATE_ALARM ) { - stateClass = "alarm"; + stateClass = 'alarm'; } else if ( alarmState == STATE_ALERT ) { - stateClass = "alert"; + stateClass = 'alert'; } - $('stateValue').set( 'text', stateStrings[alarmState] ); + $('stateValue').set('text', stateStrings[alarmState]); if ( stateClass ) { - $('stateValue').setProperty( 'class', stateClass ); + $('stateValue').setProperty('class', stateClass); } else { - $('stateValue').removeProperty( 'class' ); + $('stateValue').removeProperty('class'); } var isAlarmed = ( alarmState == STATE_ALARM || alarmState == STATE_ALERT ); @@ -114,7 +114,7 @@ function setAlarmState( currentAlarmState ) { } if ( monitorType != 'WebSite' ) { - var streamCmdParms = "view=request&request=stream&connkey="+connKey; + var streamCmdParms = 'view=request&request=stream&connkey='+connKey; if ( auth_hash ) { streamCmdParms += '&auth='+auth_hash; } @@ -141,7 +141,7 @@ function getStreamCmdFailure(xhr) { console.log(xhr); } function getStreamCmdResponse(respObj, respText) { - watchdogOk("stream"); + watchdogOk('stream'); if ( streamCmdTimer ) { streamCmdTimer = clearTimeout(streamCmdTimer); } From 71581831b5ca487894eb0997ce00dd405f0566d7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 5 Jan 2020 17:34:27 -0500 Subject: [PATCH 64/71] fix problem with the clone button material icon. Apparently file_copy doesn't work, so use content_copy instead despite it not being listed in the material icons --- web/skins/classic/views/console.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 8d8b08ff6..b910b11fa 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -187,7 +187,8 @@ getBodyTopHTML(); Date: Sun, 5 Jan 2020 17:34:40 -0500 Subject: [PATCH 65/71] controlcap needs to be larger --- 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 4ecc4c234..48747b98d 100644 --- a/web/skins/classic/js/base.js +++ b/web/skins/classic/js/base.js @@ -29,7 +29,7 @@ var popupSizes = { 'console': {'width': 750, 'height': 312}, 'control': {'width': 480, 'height': 480}, 'controlcaps': {'width': 780, 'height': 320}, - 'controlcap': {'width': 400, 'height': 400}, + 'controlcap': {'width': 600, 'height': 500}, 'cycle': {'addWidth': 32, 'minWidth': 384, 'addHeight': 62}, 'device': {'width': 260, 'height': 150}, 'devices': {'width': 400, 'height': 240}, From 2f1b725ee4f81d4119a707a10185cf9b269b3909 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 11:01:02 -0500 Subject: [PATCH 66/71] quote SQL for mysql8 --- web/skins/classic/includes/functions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 60558f8e8..328b63833 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -290,12 +290,12 @@ if ( $user and $user['Username'] ) { # zmaudit can clean the logs, but if we aren't running it, then we should clean them regularly if ( preg_match('/^\d+$/', ZM_LOG_DATABASE_LIMIT) ) { # Number of lines, instead of an interval - $rows = dbFetchOne('SELECT Count(*) AS Rows FROM Logs', 'Rows'); + $rows = dbFetchOne('SELECT Count(*) AS `Rows` FROM `Logs`', 'Rows'); if ( $rows > ZM_LOG_DATABASE_LIMIT ) { - dbQuery('DELETE low_priority FROM Logs ORDER BY TimeKey ASC LIMIT ?', array($rows - ZM_LOG_DATABASE_LIMIT)); + dbQuery('DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?', array($rows - ZM_LOG_DATABASE_LIMIT)); } } else if ( preg_match('/^\d\s*(hour|minute|day|week|month|year)$/', ZM_LOG_DATABASE_LIMIT, $matches) ) { - dbQuery('DELETE FROM Logs WHERE TimeKey < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100'); + dbQuery('DELETE FROM `Logs` WHERE `TimeKey` < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100'); } else { ZM\Error('Potentially invalid value for ZM_LOG_DATABASE_LIMIT: ' . ZM_LOG_DATABASE_LIMIT); } From 61bc0ddd0a0761a7d6ff0c90617f5fe7f241efbf Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 11:01:53 -0500 Subject: [PATCH 67/71] add missing t and merge some lines --- web/skins/classic/views/options.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index 2d1bb7ad2..0a0d99286 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -276,15 +276,10 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $ Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Path()), $canEdit ) ?> Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Type()), $canEdit ) ?> Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Scheme()), $canEdit ) ?> - Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Server()->Name()), $canEdit ) ?> - - disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) -?> - + Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Server()->Name()), $canEdit ) ?> + disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?> Events()).' using '.human_filesize($Storage->event_disk_space()) ?> - Events()) or !$canEdit ) { ?> disabled="disabled"Events()) ? ' title="Can\' delete as long as there are events stored here."' : ''?>/> + Events()) or !$canEdit ) { ?> disabled="disabled"Events()) ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/> From b85cf7d8a1eb8dd78cc5fc8ffe4ef1734940c6af Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 11:03:45 -0500 Subject: [PATCH 68/71] include error message when complaining about failing to create the hwaccell device --- src/zm_ffmpeg_camera.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index fafbf4c75..3cc634e7d 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -520,7 +520,7 @@ int FfmpegCamera::OpenFfmpeg() { ret = av_hwdevice_ctx_create(&hw_device_ctx, type, (hwaccel_device != "" ? hwaccel_device.c_str(): NULL), NULL, 0); if ( ret < 0 ) { - Error("Failed to create hwaccel device."); + Error("Failed to create hwaccel device. %s",av_make_error_string(ret).c_str()); hw_pix_fmt = AV_PIX_FMT_NONE; } else { Debug(1, "Created hwdevice for %s", hwaccel_device.c_str()); @@ -529,7 +529,7 @@ int FfmpegCamera::OpenFfmpeg() { hwFrame = zm_av_frame_alloc(); } } else { - Debug(1, "Failed to setup hwaccel."); + Debug(1, "Failed to find suitable hw_pix_fmt."); } #else Debug(1, "AVCodec not new enough for hwaccel"); From c3f8d9c364065ad063c8a8ea71c2586604ce7429 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 12:08:08 -0500 Subject: [PATCH 69/71] add php5-json as a dependency --- distros/ubuntu1604/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index 1b7b96320..ef138a3ba 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -74,7 +74,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,libfile-slurp-perl ,mysql-client | mariadb-client | virtual-mysql-client ,perl-modules - ,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc, php-json + ,php5-mysql | php-mysql, php5-gd | php-gd , php5-apcu | php-apcu , php-apc | php-apcu-bc, php-json | php5-json ,policykit-1 ,rsyslog | system-log-daemon ,zip From 971d62f60dc5be80b6ec14e12181a342eaf8829a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 12:09:34 -0500 Subject: [PATCH 70/71] encode the telemetry to utf-8 before sending. Fixes #2800 --- scripts/zmtelemetry.pl.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/zmtelemetry.pl.in b/scripts/zmtelemetry.pl.in index efd5e735e..9b5e7c89d 100644 --- a/scripts/zmtelemetry.pl.in +++ b/scripts/zmtelemetry.pl.in @@ -23,6 +23,7 @@ use strict; use bytes; +use utf8; @EXTRA_PERL_LIB@ use ZoneMinder; @@ -34,6 +35,7 @@ use Sys::MemInfo qw(totalmem); use Sys::CPU qw(cpu_count); use POSIX qw(strftime uname); use JSON::MaybeXS; +use Encode; $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; @@ -166,7 +168,7 @@ sub sendData { $req->header('content-length' => length($msg)); $req->header('connection' => 'Close'); - $req->content($msg); + $req->content(encode('UTF-8',$msg)); my $resp = $ua->request($req); my $resp_msg = $resp->decoded_content; From c0443f694abe5130469f09061f2f48757d5d9d01 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 12:24:39 -0500 Subject: [PATCH 71/71] I think we need .buildinfo as well --- utils/packpack/rsync_xfer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/packpack/rsync_xfer.sh b/utils/packpack/rsync_xfer.sh index c4b6f93e1..9f273ca96 100755 --- a/utils/packpack/rsync_xfer.sh +++ b/utils/packpack/rsync_xfer.sh @@ -27,7 +27,7 @@ echo echo "Target subfolder set to $targetfolder" echo -echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)" +echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)" rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1 if [ "$?" -eq 0 ]; then echo