From 312dab2c2050101fc02be886bc750a3e1aeafc1b Mon Sep 17 00:00:00 2001 From: Javier Gonzalez Date: Sat, 20 Apr 2019 17:14:43 +0200 Subject: [PATCH 01/37] Fixing video export view --- web/skins/classic/views/video.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/video.php b/web/skins/classic/views/video.php index aab9278d6..ca4c46f4b 100644 --- a/web/skins/classic/views/video.php +++ b/web/skins/classic/views/video.php @@ -46,7 +46,7 @@ if ( isset($_REQUEST['scale']) ) else $scale = reScale(SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE); -$Event = new Event($event['Id']); +$Event = new ZM\Event($event['Id']); $eventPath = $Event->Path(); $videoFormats = array(); From 22b61cd5b2a471d0e472c82bd57569030b12d22f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 Dec 2019 15:51:40 -0500 Subject: [PATCH 02/37] wip cleanup of AxisV2 --- .../lib/ZoneMinder/Control/AxisV2.pm | 182 +++++++++++------- 1 file changed, 113 insertions(+), 69 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm index d63236c86..8ca2c7330 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm @@ -33,6 +33,12 @@ require ZoneMinder::Control; our @ISA = qw(ZoneMinder::Control); +our $REALM = ''; +our $PROTOCOL = 'http://'; +our $USERNAME = 'admin'; +our $PASSWORD = ''; +our $ADDRESS = ''; +our $PORT = ''; # ========================================================================== # # Axis V2 Control Protocol @@ -43,59 +49,108 @@ use ZoneMinder::Logger qw(:all); use ZoneMinder::Config qw(:all); use Time::HiRes qw( usleep ); +use URI; -sub open -{ +sub open { my $self = shift; $self->loadMonitor(); +my $uri = URI->new($self->{Monitor}->{ControlAddress}); +Debug("Have " . $uri); +#my($scheme, $authority, $path, $query, $fragment) = +# $self->{Monitor}->{ControlAddress} =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|; +#Debug("Have $scheme, $authority, $path, $query, $fragment)"); - use LWP::UserAgent; - $self->{ua} = LWP::UserAgent->new; - $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION ); +# $PROTOCOL = $scheme; +#($USERNAME, $PASSWORD) = split(':', $authority); +# $ADDRESS = $path; +$ADDRESS = $uri->scheme.'://'.$uri->host().$uri->path().($uri->port()?':'.$uri->port():''); +Debug($uri->authority()); + + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->cookie_jar( {} ); + $self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION); + $self->{state} = 'closed'; + # credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string) + Debug("sendCmd credentials control address:'".$ADDRESS + ."' realm:'".$REALM + ."' username:'".$USERNAME + ."' password:'".$PASSWORD + ."'" + ); + $self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD); + + # Detect REALM + my $res = $self->{ua}->get($ADDRESS.'/cgi/ptdc.cgi'); + + if ( $res->is_success ) { $self->{state} = 'open'; -} + return; + } -sub printMsg -{ - my $self = shift; - my $msg = shift; - my $msg_len = length($msg); + if ( $res->status_line() eq '401 Unauthorized' ) { - Debug( $msg."[".$msg_len."]" ); -} - -sub sendCmd -{ - my $self = shift; - my $cmd = shift; - - my $result = undef; - - printMsg( $cmd, "Tx" ); - - #print( "http://$address/$cmd\n" ); - my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); - my $res = $self->{ua}->request($req); - - if ( $res->is_success ) - { - $result = !undef; - } - else - { - Error( "Error check failed: '".$res->status_line()."'" ); + my $headers = $res->headers(); + foreach my $k ( keys %$headers ) { + Debug("Initial Header $k => $$headers{$k}"); } - return( $result ); + if ( $$headers{'www-authenticate'} ) { + Debug("Authenticating"); + 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($ADDRESS,$REALM,$USERNAME,$PASSWORD); + $res = $self->{ua}->get($ADDRESS); + 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' +} # end sub open + +sub sendCmd { + my $self = shift; + my $cmd = shift; + + $self->printMsg($cmd, 'Tx'); + + my $url = $ADDRESS.$cmd; + my $res = $self->{ua}->get($url); + + if ( $res->is_success ) { + Debug('sndCmd command: ' . $url . ' content: '.$res->content); + return !undef; + } + + Error("Error cmd $url failed: '".$res->status_line()."'"); + + return undef; } -sub cameraReset -{ +sub cameraReset { my $self = shift; - Debug( "Camera Reset" ); - my $cmd = "/axis-cgi/admin/restart.cgi"; + Debug('Camera Reset'); + my $cmd = '/axis-cgi/admin/restart.cgi'; $self->sendCmd( $cmd ); } @@ -123,52 +178,42 @@ sub moveConLeft $self->sendCmd( $cmd ); } -sub moveConRight -{ +sub moveConRight { my $self = shift; - Debug( "Move Right" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=right"; - $self->sendCmd( $cmd ); + Debug('Move Right'); + $self->sendCmd('/axis-cgi/com/ptz.cgi?move=right'); } -sub moveConUpRight -{ +sub moveConUpRight { my $self = shift; - Debug( "Move Up/Right" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=upright"; - $self->sendCmd( $cmd ); + Debug('Move Up/Right'); + $self->sendCmd('/axis-cgi/com/ptz.cgi?move=upright'); } -sub moveConUpLeft -{ +sub moveConUpLeft { my $self = shift; Debug( "Move Up/Left" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=upleft"; - $self->sendCmd( $cmd ); + $self->sendCmd('/axis-cgi/com/ptz.cgi?move=upleft'); } -sub moveConDownRight -{ +sub moveConDownRight { my $self = shift; - Debug( "Move Down/Right" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=downright"; - $self->sendCmd( $cmd ); + Debug('Move Down/Right'); + $self->sendCmd('/axis-cgi/com/ptz.cgi?move=downright'); } -sub moveConDownLeft -{ +sub moveConDownLeft { my $self = shift; - Debug( "Move Down/Left" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=downleft"; - $self->sendCmd( $cmd ); + Debug('Move Down/Left'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=downleft'; + $self->sendCmd($cmd); } -sub moveMap -{ +sub moveMap { my $self = shift; my $params = shift; - my $xcoord = $self->getParam( $params, 'xcoord' ); - my $ycoord = $self->getParam( $params, 'ycoord' ); + my $xcoord = $self->getParam($params, 'xcoord'); + my $ycoord = $self->getParam($params, 'ycoord'); Debug( "Move Map to $xcoord,$ycoord" ); my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=".$self->{Monitor}->{Width}."&imageheight=".$self->{Monitor}->{Height}; $self->sendCmd( $cmd ); @@ -210,8 +255,7 @@ sub moveRelRight my $params = shift; my $step = $self->getParam( $params, 'panstep' ); Debug( "Step Right $step" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$step"; - $self->sendCmd( $cmd ); + $self->sendCmd("/axis-cgi/com/ptz.cgi?rpan=$step&camera=1&whoami=1"); } sub moveRelUpRight From 1865df3fe00a898bcaf565b26b2fc541729f8333 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 17:08:07 -0500 Subject: [PATCH 03/37] remove some debug, add some parenthesis to ensure logic works as intended --- web/ajax/stream.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/web/ajax/stream.php b/web/ajax/stream.php index 910b18cb5..575eaef39 100644 --- a/web/ajax/stream.php +++ b/web/ajax/stream.php @@ -119,13 +119,11 @@ if ( sem_acquire($semaphore,1) !== false ) { switch ( $data['type'] ) { case MSG_DATA_WATCH : $data = unpack('ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced', $msg); - ZM\Logger::Debug('FPS: ' . $data['fps']); $data['fps'] = round( $data['fps'], 2 ); - ZM\Logger::Debug('FPS: ' . $data['fps'] ); $data['rate'] /= RATE_BASE; $data['delay'] = round( $data['delay'], 2 ); $data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 ); - if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' ) { + if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) { $time = time(); // Regenerate auth hash after half the lifetime of the hash if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) { @@ -144,7 +142,7 @@ if ( sem_acquire($semaphore,1) !== false ) { } $data['rate'] /= RATE_BASE; $data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 ); - if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' ) { + if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) { $time = time(); // Regenerate auth hash after half the lifetime of the hash if ( (!isset($_SESSION['AuthHashGeneratedAt'])) or ( $_SESSION['AuthHashGeneratedAt'] < $time - (ZM_AUTH_HASH_TTL * 1800) ) ) { From 0571909d05c8361679964858eada7d8e1791f8ce Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 17:08:29 -0500 Subject: [PATCH 04/37] add remote_IP to log entries on php side --- web/includes/logger.php | 146 +++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 69 deletions(-) diff --git a/web/includes/logger.php b/web/includes/logger.php index 3aa8f891b..7404891b6 100644 --- a/web/includes/logger.php +++ b/web/includes/logger.php @@ -274,7 +274,7 @@ class Logger { } } } - return( $this->databaseLevel ); + return $this->databaseLevel; } public function fileLevel( $fileLevel ) { @@ -288,7 +288,7 @@ class Logger { $this->openFile(); } } - return( $this->fileLevel ); + return $this->fileLevel; } public function weblogLevel( $weblogLevel ) { @@ -303,7 +303,7 @@ class Logger { $this->weblogLevel = $weblogLevel; } } - return( $this->weblogLevel ); + return $this->weblogLevel; } public function syslogLevel( $syslogLevel ) { @@ -317,30 +317,31 @@ class Logger { $this->openSyslog(); } } - return( $this->syslogLevel ); + return $this->syslogLevel; } private function openSyslog() { - openlog( $this->id, LOG_PID|LOG_NDELAY, LOG_LOCAL1 ); + openlog($this->id, LOG_PID|LOG_NDELAY, LOG_LOCAL1); } private function closeSyslog() { closelog(); } - private function logFile( $logFile ) { - if ( preg_match( '/^(.+)\+$/', $logFile, $matches ) ) + private function logFile($logFile) { + if ( preg_match('/^(.+)\+$/', $logFile, $matches) ) { $this->logFile = $matches[1].'.'.getmypid(); - else + } else { $this->logFile = $logFile; + } } private function openFile() { if ( !$this->useErrorLog ) { - if ( $this->logFd = fopen( $this->logFile, 'a+' ) ) { - if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) { + if ( $this->logFd = fopen($this->logFile, 'a+') ) { + if ( strnatcmp(phpversion(), '5.2.0') >= 0 ) { $error = error_get_last(); - trigger_error( "Can't open log file '$logFile': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR ); + trigger_error("Can't open log file '$logFile': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR); } $this->fileLevel = self::NOLOG; } @@ -349,73 +350,80 @@ class Logger { private function closeFile() { if ( $this->logFd ) - fclose( $this->logFd ); + fclose($this->logFd); } public function logPrint( $level, $string, $file=NULL, $line=NULL ) { - if ( $level <= $this->effectiveLevel ) { - $string = preg_replace( '/[\r\n]+$/', '', $string ); - $code = self::$codes[$level]; + if ( $level > $this->effectiveLevel ) { + return; + } - $time = gettimeofday(); - $message = sprintf( '%s.%06d %s[%d].%s [%s]', strftime( '%x %H:%M:%S', $time['sec'] ), $time['usec'], $this->id, getmypid(), $code, $string ); + $string = preg_replace('/[\r\n]+$/', '', $string); + $code = self::$codes[$level]; - if ( is_null($file) ) { - if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG ) { - $backTrace = debug_backtrace(); - $file = $backTrace[1]['file']; - $line = $backTrace[1]['line']; - if ( $this->hasTerm ) - $rootPath = getcwd(); - else - $rootPath = $_SERVER['DOCUMENT_ROOT']; - $file = preg_replace( '/^'.addcslashes($rootPath,'/').'\/?/', '', $file ); - } - } + $time = gettimeofday(); + $message = sprintf('%s.%06d %s[%d].%s [%s] [%s]', strftime('%x %H:%M:%S', $time['sec']), $time['usec'], $this->id, getmypid(), $code, $_SERVER['REMOTE_ADDR'], $string); - if ( $this->useErrorLog ) - $message .= ' at '.$file.' line '.$line; - else - $message = $message; - - if ( $level <= $this->termLevel ) + if ( is_null($file) ) { + if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG ) { + $backTrace = debug_backtrace(); + $file = $backTrace[1]['file']; + $line = $backTrace[1]['line']; if ( $this->hasTerm ) - print( $message."\n" ); + $rootPath = getcwd(); else - print( preg_replace( "/\n/", '
', htmlspecialchars($message) ).'
' ); - - if ( $level <= $this->fileLevel ) - if ( $this->useErrorLog ) { - if ( !error_log( $message."\n", 3, $this->logFile ) ) { - if ( strnatcmp( phpversion(), '5.2.0' ) >= 0 ) { - $error = error_get_last(); - trigger_error( "Can't write to log file '".$this->logFile."': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR ); - } - } - } elseif ( $this->logFd ) { - fprintf( $this->logFd, $message."\n" ); - } - - $message = $code.' ['.$string.']'; - if ( $level <= $this->syslogLevel ) - syslog( self::$syslogPriorities[$level], $message ); - if ( $level <= $this->databaseLevel ) { - try { - global $dbConn; - $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) values ( ?, ?, ?, ?, ?, ?, ?, ? )'; - $stmt = $dbConn->prepare( $sql ); - $result = $stmt->execute( array( sprintf( '%d.%06d', $time['sec'], $time['usec'] ), $this->id, getmypid(), $level, $code, $string, $file, $line ) ); - } catch(PDOException $ex) { - $this->databaseLevel = self::NOLOG; - Error("Can't write log entry '$sql': ". $ex->getMessage()); - } + $rootPath = $_SERVER['DOCUMENT_ROOT']; + $file = preg_replace('/^'.addcslashes($rootPath,'/').'\/?/', '', $file); } - // This has to be last as trigger_error can be fatal - if ( $level <= $this->weblogLevel ) { - if ( $this->useErrorLog ) - error_log( $message, 0 ); - else - trigger_error( $message, self::$phpErrorLevels[$level] ); + } + + if ( $this->useErrorLog ) { + $message .= ' at '.$file.' line '.$line; + } else { + $message = $message; + } + + if ( $level <= $this->termLevel ) { + if ( $this->hasTerm ) + print($message."\n"); + else + print(preg_replace("/\n/", '
', htmlspecialchars($message) ).'
'); + } + + if ( $level <= $this->fileLevel ) { + if ( $this->useErrorLog ) { + if ( !error_log($message."\n", 3, $this->logFile) ) { + if ( strnatcmp(phpversion(), '5.2.0') >= 0 ) { + $error = error_get_last(); + trigger_error("Can't write to log file '".$this->logFile."': ".$error['message'].' @ '.$error['file'].'/'.$error['line'], E_USER_ERROR); + } + } + } else if ( $this->logFd ) { + fprintf($this->logFd, $message."\n"); + } + } + + $message = $code.' ['.$string.']'; + if ( $level <= $this->syslogLevel ) + syslog( self::$syslogPriorities[$level], $message ); + + if ( $level <= $this->databaseLevel ) { + try { + global $dbConn; + $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )'; + $stmt = $dbConn->prepare($sql); + $result = $stmt->execute(array(sprintf('%d.%06d', $time['sec'], $time['usec']), $this->id, getmypid(), $level, $code, $string, $file, $line)); + } catch(PDOException $ex) { + $this->databaseLevel = self::NOLOG; + Error("Can't write log entry '$sql': ". $ex->getMessage()); + } + } + // This has to be last as trigger_error can be fatal + if ( $level <= $this->weblogLevel ) { + if ( $this->useErrorLog ) { + error_log($message, 0); + } else { + trigger_error($message, self::$phpErrorLevels[$level]); } } } From c64de372a720e7651dddb8c03ac3b38d06037dcd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 7 Jan 2020 17:08:57 -0500 Subject: [PATCH 05/37] when auth_hash changes, update various CmdParms --- web/skins/classic/views/js/watch.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index c151ba3ec..1dc756a0e 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -229,12 +229,19 @@ function getStreamCmdResponse(respObj, respText) { } // end if canEditMonitors if ( streamStatus.auth ) { + auth_hash = streamStatus.auth; console.log("Have a new auth hash" + streamStatus.auth); // Try to reload the image stream. var streamImg = $('liveStream'); if ( streamImg ) { streamImg.src = streamImg.src.replace(/auth=\w+/i, 'auth='+streamStatus.auth); } + streamCmdParms = streamCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + statusCmdParms = statusCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + eventCmdParms = eventCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + actParms = actParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + controlParms = controlParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); + } // end if have a new auth hash } // end if respObj.status } else { @@ -473,6 +480,9 @@ function getActResponse( respObj, respText ) { function deleteEvent( event, eventId ) { var actParms = "view=request&request=event&action=delete&id="+eventId; + if ( auth_hash ) { + actParms += '&auth='+auth_hash; + } var actReq = new Request.JSON( { url: thisUrl, method: 'post', From f13a7199e1603952b17eece324a1b8bbc816e19e Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 7 Jan 2020 21:53:55 -0600 Subject: [PATCH 06/37] fix eslint --- web/skins/classic/views/js/watch.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 1dc756a0e..242ec80f0 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -241,7 +241,6 @@ function getStreamCmdResponse(respObj, respText) { eventCmdParms = eventCmdParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); actParms = actParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); controlParms = controlParms.replace(/auth=\w+/i, 'auth='+streamStatus.auth); - } // end if have a new auth hash } // end if respObj.status } else { From 28a4bef6baf5afc125922534758a5f7c284a45f1 Mon Sep 17 00:00:00 2001 From: Alex Porosanu Date: Thu, 9 Jan 2020 21:58:23 +0200 Subject: [PATCH 07/37] fix tar invocation for *BSD platforms "--xform" switch is not supported by tar on BSD platforms i.e. *BSD, MacOS, etc. As such, use "-s" switch on these platforms, with a similar regexp. --- web/skins/classic/includes/export_functions.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/includes/export_functions.php b/web/skins/classic/includes/export_functions.php index 8ce0fba5a..d43c697e3 100644 --- a/web/skins/classic/includes/export_functions.php +++ b/web/skins/classic/includes/export_functions.php @@ -940,6 +940,8 @@ function exportEvents( $archive = ''; if ( $exportFormat == 'tar' ) { $archive = ZM_DIR_EXPORTS.'/'.$export_root.($connkey?'_'.$connkey:'').'.tar'; + $version = shell_exec('tar -v'); + $command = 'tar --create --dereference'; if ( $exportCompressed ) { $archive .= '.gz'; @@ -947,8 +949,11 @@ function exportEvents( $exportFormat .= '.gz'; } if ( $exportStructure == 'flat' ) { - //strip file paths if we - $command .= " --xform='s#^.+/##x'"; + if (preg_match("/BSD/i", $version)) { + $command .= " -s '#^.*/##'"; + } else { + $command .= " --xform='s#^.+/##x'"; + } } $command .= ' --file='.escapeshellarg($archive); } elseif ( $exportFormat == 'zip' ) { From ef4ecd40fbd6e03a6958d7543735f7a7ddd461a0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 12:44:59 -0500 Subject: [PATCH 08/37] Set defaults before saving Objects --- web/includes/Object.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/web/includes/Object.php b/web/includes/Object.php index 1c17ce312..9f29aed88 100644 --- a/web/includes/Object.php +++ b/web/includes/Object.php @@ -110,8 +110,9 @@ class ZM_Object { public static function _find_one($class, $parameters = array(), $options = array() ) { global $object_cache; - if ( ! isset($object_cache[$class]) ) + if ( ! isset($object_cache[$class]) ) { $object_cache[$class] = array(); + } $cache = &$object_cache[$class]; if ( ( count($parameters) == 1 ) and @@ -290,6 +291,16 @@ Logger::Debug("$k => Have default for $v: "); $this->set($new_values); } + foreach ( $this->defaults as $field => $default ) { + if ( (!array_key_exists($field, $this)) or empty($this->{$field}) ) { + if ( is_array($default) ) { + $this->{$field} = $default['default']; + } else { + $this->{$field} = $default; + } + } + } + $fields = array_filter( $this->defaults, function($v) { From d433590f74663d5db6a09416c15c08cfbce16da7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 12:45:30 -0500 Subject: [PATCH 09/37] use find_one in stead of new to use Cached Server --- web/includes/Monitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index b725963f2..a15e88d2d 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -128,7 +128,7 @@ class Monitor extends ZM_Object { } public function Server() { - return new Server($this->{'ServerId'}); + return Server::find_one(array('Id'=>$this->{'ServerId'})); } public function __call($fn, array $args){ From f61f6eaf7dda79ec31c5031747ea277c5e9f6d71 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 12:45:47 -0500 Subject: [PATCH 10/37] remove line cutnpasted erroneously --- web/includes/actions/monitor.php | 1 - 1 file changed, 1 deletion(-) diff --git a/web/includes/actions/monitor.php b/web/includes/actions/monitor.php index 823a06ff2..f1223a6f9 100644 --- a/web/includes/actions/monitor.php +++ b/web/includes/actions/monitor.php @@ -219,7 +219,6 @@ if ( $action == 'monitor' ) { } else { ZM\Error('Error saving new Monitor.'); - $error_message = dbError($sql); return; } } From f8e54ba6e30781db0fd592636fd5d05350e4a522 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 16:41:22 -0500 Subject: [PATCH 11/37] spacing, quotes --- .../lib/ZoneMinder/Control/AxisV2.pm | 497 ++++++++---------- 1 file changed, 226 insertions(+), 271 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm index d63236c86..b870c46e4 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm @@ -1,6 +1,6 @@ # ========================================================================== # -# ZoneMinder Axis version 2 API Control Protocol Module, $Date$, $Revision$ +# ZoneMinder Axis version 2 API Control Protocol Module # Copyright (C) 2001-2008 Philip Coombes # # This program is free software; you can redistribute it and/or @@ -46,346 +46,301 @@ use Time::HiRes qw( usleep ); sub open { - my $self = shift; + my $self = shift; - $self->loadMonitor(); + $self->loadMonitor(); - use LWP::UserAgent; - $self->{ua} = LWP::UserAgent->new; - $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION ); + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION); - $self->{state} = 'open'; + $self->{state} = 'open'; } -sub printMsg -{ - my $self = shift; - my $msg = shift; - my $msg_len = length($msg); +sub sendCmd { + my $self = shift; + my $cmd = shift; - Debug( $msg."[".$msg_len."]" ); + my $result = undef; + + $self->printMsg($cmd, 'Tx'); + + #print( "http://$address/$cmd\n" ); + my $req = HTTP::Request->new(GET=>'http://'.$self->{Monitor}->{ControlAddress}.'/'.$cmd); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) { + $result = !undef; + } else { + Error('Error check failed: \''.$res->status_line().'\''); + } + + return $result; } -sub sendCmd -{ - my $self = shift; - my $cmd = shift; - - my $result = undef; - - printMsg( $cmd, "Tx" ); - - #print( "http://$address/$cmd\n" ); - my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); - my $res = $self->{ua}->request($req); - - if ( $res->is_success ) - { - $result = !undef; - } - else - { - Error( "Error check failed: '".$res->status_line()."'" ); - } - - return( $result ); +sub cameraReset { + my $self = shift; + Debug('Camera Reset'); + my $cmd = '/axis-cgi/admin/restart.cgi'; + $self->sendCmd($cmd); } -sub cameraReset -{ - my $self = shift; - Debug( "Camera Reset" ); - my $cmd = "/axis-cgi/admin/restart.cgi"; - $self->sendCmd( $cmd ); +sub moveConUp { + my $self = shift; + Debug('Move Up'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=up'; + $self->sendCmd($cmd); } -sub moveConUp -{ - my $self = shift; - Debug( "Move Up" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=up"; - $self->sendCmd( $cmd ); +sub moveConDown { + my $self = shift; + Debug('Move Down'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=down'; + $self->sendCmd($cmd); } -sub moveConDown -{ - my $self = shift; - Debug( "Move Down" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=down"; - $self->sendCmd( $cmd ); +sub moveConLeft { + my $self = shift; + Debug('Move Left'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=left'; + $self->sendCmd($cmd); } -sub moveConLeft -{ - my $self = shift; - Debug( "Move Left" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=left"; - $self->sendCmd( $cmd ); +sub moveConRight { + my $self = shift; + Debug('Move Right'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=right'; + $self->sendCmd($cmd); } -sub moveConRight -{ - my $self = shift; - Debug( "Move Right" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=right"; - $self->sendCmd( $cmd ); +sub moveConUpRight { + my $self = shift; + Debug('Move Up/Right'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=upright'; + $self->sendCmd($cmd); } -sub moveConUpRight -{ - my $self = shift; - Debug( "Move Up/Right" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=upright"; - $self->sendCmd( $cmd ); +sub moveConUpLeft { + my $self = shift; + Debug('Move Up/Left'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=upleft'; + $self->sendCmd($cmd); } -sub moveConUpLeft -{ - my $self = shift; - Debug( "Move Up/Left" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=upleft"; - $self->sendCmd( $cmd ); +sub moveConDownRight { + my $self = shift; + Debug('Move Down/Right'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=downright'; + $self->sendCmd( $cmd ); } -sub moveConDownRight -{ - my $self = shift; - Debug( "Move Down/Right" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=downright"; - $self->sendCmd( $cmd ); +sub moveConDownLeft { + my $self = shift; + Debug('Move Down/Left'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=downleft'; + $self->sendCmd($cmd); } -sub moveConDownLeft -{ - my $self = shift; - Debug( "Move Down/Left" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=downleft"; - $self->sendCmd( $cmd ); +sub moveMap { + my $self = shift; + my $params = shift; + my $xcoord = $self->getParam($params, 'xcoord'); + my $ycoord = $self->getParam($params, 'ycoord'); + Debug("Move Map to $xcoord,$ycoord"); + my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=".$self->{Monitor}->{Width}.'&imageheight='.$self->{Monitor}->{Height}; + $self->sendCmd($cmd); } -sub moveMap -{ - my $self = shift; - my $params = shift; - my $xcoord = $self->getParam( $params, 'xcoord' ); - my $ycoord = $self->getParam( $params, 'ycoord' ); - Debug( "Move Map to $xcoord,$ycoord" ); - my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=".$self->{Monitor}->{Width}."&imageheight=".$self->{Monitor}->{Height}; - $self->sendCmd( $cmd ); +sub moveRelUp { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'tiltstep'); + Debug("Step Up $step"); + my $cmd = '/axis-cgi/com/ptz.cgi?rtilt='.$step; + $self->sendCmd($cmd); } -sub moveRelUp -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'tiltstep' ); - Debug( "Step Up $step" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=$step"; - $self->sendCmd( $cmd ); +sub moveRelDown { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'tiltstep'); + Debug("Step Down $step"); + my $cmd = '/axis-cgi/com/ptz.cgi?rtilt=-'.$step; + $self->sendCmd($cmd); } -sub moveRelDown -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'tiltstep' ); - Debug( "Step Down $step" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=-$step"; - $self->sendCmd( $cmd ); +sub moveRelLeft { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'panstep'); + Debug("Step Left $step"); + my $cmd = '/axis-cgi/com/ptz.cgi?rpan=-'.$step; + $self->sendCmd($cmd); } -sub moveRelLeft -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'panstep' ); - Debug( "Step Left $step" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$step"; - $self->sendCmd( $cmd ); +sub moveRelRight { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'panstep'); + Debug("Step Right $step"); + my $cmd = '/axis-cgi/com/ptz.cgi?rpan='$step; + $self->sendCmd($cmd); } -sub moveRelRight -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'panstep' ); - Debug( "Step Right $step" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$step"; - $self->sendCmd( $cmd ); +sub moveRelUpRight { + my $self = shift; + my $params = shift; + my $panstep = $self->getParam($params, 'panstep'); + my $tiltstep = $self->getParam($params, 'tiltstep'); + Debug("Step Up/Right $tiltstep/$panstep"); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=$tiltstep"; + $self->sendCmd($cmd); } -sub moveRelUpRight -{ - my $self = shift; - my $params = shift; - my $panstep = $self->getParam( $params, 'panstep' ); - my $tiltstep = $self->getParam( $params, 'tiltstep' ); - Debug( "Step Up/Right $tiltstep/$panstep" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=$tiltstep"; - $self->sendCmd( $cmd ); +sub moveRelUpLeft { + my $self = shift; + my $params = shift; + my $panstep = $self->getParam($params, 'panstep'); + my $tiltstep = $self->getParam($params, 'tiltstep'); + Debug("Step Up/Left $tiltstep/$panstep"); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep"; + $self->sendCmd($cmd); } -sub moveRelUpLeft -{ - my $self = shift; - my $params = shift; - my $panstep = $self->getParam( $params, 'panstep' ); - my $tiltstep = $self->getParam( $params, 'tiltstep' ); - Debug( "Step Up/Left $tiltstep/$panstep" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep"; - $self->sendCmd( $cmd ); +sub moveRelDownRight { + my $self = shift; + my $params = shift; + my $panstep = $self->getParam($params, 'panstep'); + my $tiltstep = $self->getParam($params, 'tiltstep'); + Debug("Step Down/Right $tiltstep/$panstep"); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=-$tiltstep"; + $self->sendCmd($cmd); } -sub moveRelDownRight -{ - my $self = shift; - my $params = shift; - my $panstep = $self->getParam( $params, 'panstep' ); - my $tiltstep = $self->getParam( $params, 'tiltstep' ); - Debug( "Step Down/Right $tiltstep/$panstep" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=-$tiltstep"; - $self->sendCmd( $cmd ); +sub moveRelDownLeft { + my $self = shift; + my $params = shift; + my $panstep = $self->getParam($params, 'panstep'); + my $tiltstep = $self->getParam($params, 'tiltstep'); + Debug("Step Down/Left $tiltstep/$panstep"); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=-$tiltstep"; + $self->sendCmd($cmd); } -sub moveRelDownLeft -{ - my $self = shift; - my $params = shift; - my $panstep = $self->getParam( $params, 'panstep' ); - my $tiltstep = $self->getParam( $params, 'tiltstep' ); - Debug( "Step Down/Left $tiltstep/$panstep" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=-$tiltstep"; - $self->sendCmd( $cmd ); +sub zoomRelTele { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'step'); + Debug('Zoom Tele'); + my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=$step"; + $self->sendCmd($cmd); } -sub zoomRelTele -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'step' ); - Debug( "Zoom Tele" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=$step"; - $self->sendCmd( $cmd ); +sub zoomRelWide { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'step'); + Debug('Zoom Wide'); + my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=-$step"; + $self->sendCmd($cmd); } -sub zoomRelWide -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'step' ); - Debug( "Zoom Wide" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=-$step"; - $self->sendCmd( $cmd ); +sub focusRelNear { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'step'); + Debug('Focus Near'); + my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=-$step"; + $self->sendCmd($cmd); } -sub focusRelNear -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'step' ); - Debug( "Focus Near" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=-$step"; - $self->sendCmd( $cmd ); +sub focusRelFar { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'step'); + Debug('Focus Far'); + my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=$step"; + $self->sendCmd($cmd); } -sub focusRelFar -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'step' ); - Debug( "Focus Far" ); - my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=$step"; - $self->sendCmd( $cmd ); +sub focusAuto { + my $self = shift; + Debug('Focus Auto'); + my $cmd = '/axis-cgi/com/ptz.cgi?autofocus=on'; + $self->sendCmd($cmd); } -sub focusAuto -{ - my $self = shift; - Debug( "Focus Auto" ); - my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=on"; - $self->sendCmd( $cmd ); +sub focusMan { + my $self = shift; + Debug('Focus Manual'); + my $cmd = '/axis-cgi/com/ptz.cgi?autofocus=off'; + $self->sendCmd($cmd); } -sub focusMan -{ - my $self = shift; - Debug( "Focus Manual" ); - my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=off"; - $self->sendCmd( $cmd ); +sub irisRelOpen { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'step'); + Debug('Iris Open'); + my $cmd = "/axis-cgi/com/ptz.cgi?riris=$step"; + $self->sendCmd($cmd); } -sub irisRelOpen -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'step' ); - Debug( "Iris Open" ); - my $cmd = "/axis-cgi/com/ptz.cgi?riris=$step"; - $self->sendCmd( $cmd ); +sub irisRelClose { + my $self = shift; + my $params = shift; + my $step = $self->getParam($params, 'step'); + Debug('Iris Close'); + my $cmd = "/axis-cgi/com/ptz.cgi?riris=-$step"; + $self->sendCmd($cmd); } -sub irisRelClose -{ - my $self = shift; - my $params = shift; - my $step = $self->getParam( $params, 'step' ); - Debug( "Iris Close" ); - my $cmd = "/axis-cgi/com/ptz.cgi?riris=-$step"; - $self->sendCmd( $cmd ); +sub irisAuto { + my $self = shift; + Debug('Iris Auto'); + my $cmd = '/axis-cgi/com/ptz.cgi?autoiris=on'; + $self->sendCmd($cmd); } -sub irisAuto -{ - my $self = shift; - Debug( "Iris Auto" ); - my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=on"; - $self->sendCmd( $cmd ); +sub irisMan { + my $self = shift; + Debug('Iris Manual'); + my $cmd = '/axis-cgi/com/ptz.cgi?autoiris=off'; + $self->sendCmd($cmd); } -sub irisMan -{ - my $self = shift; - Debug( "Iris Manual" ); - my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=off"; - $self->sendCmd( $cmd ); +sub presetClear { + my $self = shift; + my $params = shift; + my $preset = $self->getParam($params, 'preset'); + Debug("Clear Preset $preset"); + my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset"; + $self->sendCmd($cmd); } -sub presetClear -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - Debug( "Clear Preset $preset" ); - my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset"; - $self->sendCmd( $cmd ); +sub presetSet { + my $self = shift; + my $params = shift; + my $preset = $self->getParam($params, 'preset'); + Debug("Set Preset $preset"); + my $cmd = "/axis-cgi/com/ptz.cgi?setserverpresetno=$preset"; + $self->sendCmd($cmd); } -sub presetSet -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - Debug( "Set Preset $preset" ); - my $cmd = "/axis-cgi/com/ptz.cgi?setserverpresetno=$preset"; - $self->sendCmd( $cmd ); +sub presetGoto { + my $self = shift; + my $params = shift; + my $preset = $self->getParam($params, 'preset'); + Debug("Goto Preset $preset"); + my $cmd = "/axis-cgi/com/ptz.cgi?gotoserverpresetno=$preset"; + $self->sendCmd($cmd); } -sub presetGoto -{ - my $self = shift; - my $params = shift; - my $preset = $self->getParam( $params, 'preset' ); - Debug( "Goto Preset $preset" ); - my $cmd = "/axis-cgi/com/ptz.cgi?gotoserverpresetno=$preset"; - $self->sendCmd( $cmd ); -} - -sub presetHome -{ - my $self = shift; - Debug( "Home Preset" ); - my $cmd = "/axis-cgi/com/ptz.cgi?move=home"; - $self->sendCmd( $cmd ); +sub presetHome { + my $self = shift; + Debug('Home Preset'); + my $cmd = '/axis-cgi/com/ptz.cgi?move=home'; + $self->sendCmd($cmd); } 1; From 6da998b0c028357c545c111a83f517c87bfbcf83 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 16:42:18 -0500 Subject: [PATCH 12/37] code comments and parenthesis --- src/zm_logger.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 1b8afc517..1f52c86dc 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -156,6 +156,7 @@ void Logger::initialise(const std::string &id, const Options &options) { if ( options.mTerminalLevel != NOOPT ) tempTerminalLevel = options.mTerminalLevel; + // DEBUG1 == 1. So >= DEBUG1, we set to DEBUG9?! Why? if ( options.mDatabaseLevel != NOOPT ) tempDatabaseLevel = options.mDatabaseLevel; else @@ -359,7 +360,7 @@ Logger::Level Logger::databaseLevel(Logger::Level databaseLevel) { if ( databaseLevel > NOOPT ) { databaseLevel = limit(databaseLevel); if ( mDatabaseLevel != databaseLevel ) { - if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) { + if ( (databaseLevel > NOLOG) && (mDatabaseLevel <= NOLOG) ) { // <= NOLOG would be NOOPT if ( !zmDbConnect() ) { databaseLevel = NOLOG; } From 5ee015873513dd929c797d6f0057738d05839ed8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 16:42:41 -0500 Subject: [PATCH 13/37] Set defaults for vars == '' --- web/includes/Object.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/includes/Object.php b/web/includes/Object.php index 9f29aed88..bf647c230 100644 --- a/web/includes/Object.php +++ b/web/includes/Object.php @@ -291,11 +291,13 @@ Logger::Debug("$k => Have default for $v: "); $this->set($new_values); } + # Set defaults. Note that we only replace "" with null, not other values + # because for example if we want to clear TimestampFormat, we clear it, but the default is a string value foreach ( $this->defaults as $field => $default ) { - if ( (!array_key_exists($field, $this)) or empty($this->{$field}) ) { + if ( (!array_key_exists($field, $this)) or ($this->{$field} == '') ) { if ( is_array($default) ) { $this->{$field} = $default['default']; - } else { + } else if ( $default == null ) { $this->{$field} = $default; } } From 9b2a5b2261b41afbe857bf324ba0ded2387ea656 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 19:06:34 -0500 Subject: [PATCH 14/37] Add table column definitions so we can use perl code to actually create or update monitors --- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm | 167 ++++++++++++++++++- 1 file changed, 165 insertions(+), 2 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm index 47ec7c557..963f75638 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm @@ -36,9 +36,172 @@ require ZoneMinder::Server; #our @ISA = qw(Exporter ZoneMinder::Base); use parent qw(ZoneMinder::Object); -use vars qw/ $table $primary_key /; +use vars qw/ $table $primary_key %fields $serial %defaults $debug/; $table = 'Monitors'; -$primary_key = 'Id'; +$serial = $primary_key = 'Id'; +%fields = map { $_ => $_ } qw( + Id + Name + Notes + ServerId + StorageId + Type + Function + Enabled + LinkedMonitors + Triggers + Device + Channel + Format + V4LMultiBuffer + V4LCapturesPerFrame + Protocol + Method + Host + Port + SubPath + Path + Options + User + Pass + Width + Height + Colours + Palette + Orientation + Deinterlacing + DecoderHWAccelName + DecoderHWAccelDevice + SaveJPEGs + VideoWriter + OutputCodec + OutputContainer + EncoderParameters + RecordAudio + RTSPDescribe + Brightness + Contrast + Hue + Colour + EventPrefix + LabelFormat + LabelX + LabelY + LabelSize + ImageBufferCount + WarmupCount + PreEventCount + PostEventCount + StreamReplayBuffer + AlarmFrameCount + SectionLength + MinSectionLength + FrameSkip + MotionFrameSkip + AnalysisFPSLimit + AnalysisUpdateDelay + MaxFPS + AlarmMaxFPS + FPSReportInterval + RefBlendPerc + AlarmRefBlendPerc + Controllable + ControlId + ControlDevice + ControlAddress + AutoStopTimeout + TrackMotion + TrackDelay + ReturnLocation + ReturnDelay + DefaultRate + DefaultScale + SignalCheckPoints + SignalCheckColour + WebColour + Exif + Sequence + ); + +%defaults = ( + ServerId => 0, + StorageId => 0, + Type => 'Ffmpeg', + Function => 'Mocord', + Enabled => 1, + LinkedMonitors => undef, + Device => '', + Channel => 0, + Format => 0, + V4LMultiBuffer => undef, + V4LCapturesPerFrame => 1, + Protocol => undef, + Method => '', + Host => undef, + Port => '', + SubPath => '', + Path => undef, + Options => undef, + User => undef, + Pass => undef, + Width => undef, + Height => undef, + Colours => 4, + Palette => 0, + Orientation => undef, + Deinterlacing => 0, + DecoderHWAccelName => undef, + DecoderHWAccelDevice => undef, + SaveJPEGs => 3, + VideoWriter => 0, + OutputCodec => undef, + OutputContainer => undef, + EncoderParameters => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n", + RecordAudio=>0, + RTSPDescribe=>0, + Brightness => -1, + Contrast => -1, + Hue => -1, + Colour => -1, + EventPrefix => 'Event-', + LabelFormat => '%N - %d/%m/%y %H:%M:%S', + LabelX => 0, + LabelY => 0, + LabelSize => 1, + ImageBufferCount => 20, + WarmupCount => 0, + PreEventCount => 5, + PostEventCount => 5, + StreamReplayBuffer => 0, + AlarmFrameCount => 1, + SectionLength => 600, + MinSectionLength => 10, + FrameSkip => 0, + MotionFrameSkip => 0, + AnalysisFPSLimit => undef, + AnalysisUpdateDelay => 0, + MaxFPS => undef, + AlarmMaxFPS => undef, + FPSReportInterval => 100, + RefBlendPerc => 6, + AlarmRefBlendPerc => 6, + Controllable => 0, + ControlId => undef, + ControlDevice => undef, + ControlAddress => undef, + AutoStopTimeout => undef, + TrackMotion => 0, + TrackDelay => undef, + ReturnLocation => -1, + ReturnDelay => undef, + DefaultRate => 100, + DefaultScale => 100, + SignalCheckPoints => 0, + SignalCheckColour => '#0000BE', + WebColour => '#ff0000', + Exif => 0, + Sequence => undef, + ); sub Server { return new ZoneMinder::Server( $_[0]{ServerId} ); From 6a4b66a792ebe71607df6a293f37e0eb16a5bb6b Mon Sep 17 00:00:00 2001 From: PrplHaz4 Date: Fri, 10 Jan 2020 19:44:06 -0500 Subject: [PATCH 15/37] add 3840x2160 4k UHD to monitor dropdown I think this is fairly common in consumer IP cams now... --- web/skins/classic/views/monitor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 63089dd51..fefeed34a 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -872,6 +872,7 @@ if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) { '1920x1080'=>'1920x1080 1080p', '2048x1536'=>'2048x1536 3MP', '2592x1944'=>'2592x1944 5MP', + '3840x2160'=>'3840x2160 4K UHD', ), $monitor->Width().'x'.$monitor->Height() ); ?> From 0c478c7962730b7b5300031460d7a2036160e363 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 20:13:09 -0500 Subject: [PATCH 16/37] fix Monitor->Server --- web/includes/Monitor.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index a15e88d2d..9f6f75ffa 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -128,7 +128,14 @@ class Monitor extends ZM_Object { } public function Server() { - return Server::find_one(array('Id'=>$this->{'ServerId'})); + if ( !property_exists($this, 'Server') ) { + if ( $this->ServerId() ) + $_this->{'Server'} = Server::find_one(array('Id'=>$this->{'ServerId'})); + if ( !property_exists($this, 'Server') ) { + $this->{'Server'} = new Server(); + } + } + return $this->{'Server'}; } public function __call($fn, array $args){ From 398688550b68045782d4dedd63733b99e38f4549 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 10 Jan 2020 20:15:52 -0500 Subject: [PATCH 17/37] fixtypo --- web/includes/Monitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 9f6f75ffa..3505e83db 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -130,7 +130,7 @@ class Monitor extends ZM_Object { public function Server() { if ( !property_exists($this, 'Server') ) { if ( $this->ServerId() ) - $_this->{'Server'} = Server::find_one(array('Id'=>$this->{'ServerId'})); + $this->{'Server'} = Server::find_one(array('Id'=>$this->{'ServerId'})); if ( !property_exists($this, 'Server') ) { $this->{'Server'} = new Server(); } From 8dfe7460f348c60a749a3e167e76b457b0f35b6e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 11 Jan 2020 10:21:29 -0500 Subject: [PATCH 18/37] revert bogus change --- distros/ubuntu1604/conf/apache2/zoneminder.conf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/distros/ubuntu1604/conf/apache2/zoneminder.conf b/distros/ubuntu1604/conf/apache2/zoneminder.conf index 2b8bb37c6..e3164d36c 100644 --- a/distros/ubuntu1604/conf/apache2/zoneminder.conf +++ b/distros/ubuntu1604/conf/apache2/zoneminder.conf @@ -1,3 +1,11 @@ +# Remember to enable cgi mod (i.e. "a2enmod cgi"). +ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin" + + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + AllowOverride All + Require all granted + + # Order matters. This alias must come first. Alias /zm/cache /var/cache/zoneminder/cache @@ -23,14 +31,6 @@ Alias /zm /usr/share/zoneminder/www -# Remember to enable cgi mod (i.e. "a2enmod cgi"). -ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin" - - Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch - AllowOverride All - Require all granted - - # For better visibility, the following directives have been migrated from the # default .htaccess files included with the CakePHP project. # Parameters not set here are inherited from the parent directive above. From f6d10e84f297525c981907de3b5d2ed85429f62e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 12 Jan 2020 18:07:20 -0500 Subject: [PATCH 19/37] Fix basic auth. TUrn ControlAddress into a URI if it isn't one --- scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm index 62ce79b82..ddb1dbe54 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm @@ -51,8 +51,12 @@ sub open { my $self = shift; $self->loadMonitor(); + if ( $self->{Monitor}->{ControlAddress} !~ /^\w+:\/\// ) { + # Has no scheme at the beginning, so won't parse as a URI + $self->{Monitor}->{ControlAddress} = 'http://'.$self->{Monitor}->{ControlAddress}; + } my $uri = URI->new($self->{Monitor}->{ControlAddress}); - $ADDRESS = $uri->scheme.'://'.$uri->host().$uri->path().($uri->port()?':'.$uri->port():''); + $ADDRESS = $uri->scheme.'://'.$uri->authority().$uri->path().($uri->port()?':'.$uri->port():''); use LWP::UserAgent; $self->{ua} = LWP::UserAgent->new; From f7e23598187599785e1caccd79ac16469161cacf Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 10:57:56 -0500 Subject: [PATCH 20/37] Implement a clear_cache function so that we can free up cached objects --- web/includes/Event.php | 4 ++++ web/includes/Object.php | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/web/includes/Event.php b/web/includes/Event.php index da633f439..2ed20f95e 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -47,6 +47,10 @@ class Event extends ZM_Object { return ZM_Object::_find_one(get_class(), $parameters, $options); } + public static function clear_cahce() { + return ZM_Object::_clear_cache(get_class()); + } + public function Storage( $new = null ) { if ( $new ) { $this->{'Storage'} = $new; diff --git a/web/includes/Object.php b/web/includes/Object.php index bf647c230..cc595cd74 100644 --- a/web/includes/Object.php +++ b/web/includes/Object.php @@ -128,6 +128,11 @@ class ZM_Object { return $results[0]; } + public static function _clear_cache($class) { + global $object_cache; + $object_cache[$class] = array(); + } + public static function Objects_Indexed_By_Id($class) { $results = array(); foreach ( ZM_Object::_find($class, null, array('order'=>'lower(Name)')) as $Object ) { From 0afcbe626c2d6249a8333573f991e79df2fbb29f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 12:51:30 -0500 Subject: [PATCH 21/37] remove redundant logging line. Connect() will do the logging --- src/zm_remote_camera_http.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp index 96c3707ff..f725d17b9 100644 --- a/src/zm_remote_camera_http.cpp +++ b/src/zm_remote_camera_http.cpp @@ -1060,7 +1060,6 @@ int RemoteCameraHttp::PreCapture() { if ( sd < 0 ) { Connect(); if ( sd < 0 ) { - Error("Unable to connect to camera"); return -1; } mode = SINGLE_IMAGE; From 952526819271f4d233d124101b912c4b39e2a139 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 12:52:34 -0500 Subject: [PATCH 22/37] Wait 5 seconds instead of 1 after failure to connect. Reduces error logs filling up db. --- src/zmc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zmc.cpp b/src/zmc.cpp index ad9dea406..511e019ab 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -350,7 +350,7 @@ int main(int argc, char *argv[]) { } if ( result < 0 ) { // Failure, try reconnecting - sleep(1); + sleep(5); break; } } // end while ! zm_terminate From 6cd76ee2ffc7bd8c882660a0d5cdd67e8a15087b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 12:53:05 -0500 Subject: [PATCH 23/37] Clear cache after loading Events so as to free ram. --- web/includes/Storage.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/includes/Storage.php b/web/includes/Storage.php index 286cec8da..a127acd2f 100644 --- a/web/includes/Storage.php +++ b/web/includes/Storage.php @@ -116,13 +116,14 @@ class Storage extends ZM_Object { $used = dbFetchOne('SELECT SUM(DiskSpace) AS DiskSpace FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL', 'DiskSpace', array($this->Id())); do { - # Do in batches of 1000 so as to not useup all ram + # Do in batches of 1000 so as to not useup all ram, Event will do caching though... $events = Event::find(array('StorageId'=>$this->Id(), 'DiskSpace'=>null), array('limit'=>1000)); foreach ( $events as $Event ) { $Event->Storage($this); // Prevent further db hit # DiskSpace will update the event $used += $Event->DiskSpace(); } #end foreach + Event::clear_cache(); } while ( count($events) == 1000 ); $this->{'DiskSpace'} = $used; } From b11815cfa91f636743081aba1c522122288a5285 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 12:53:50 -0500 Subject: [PATCH 24/37] Introduce Storage->EventCount to get the # of events per storage without actually loading all events. --- web/includes/Storage.php | 7 +++++++ web/skins/classic/views/options.php | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/web/includes/Storage.php b/web/includes/Storage.php index 286cec8da..30b0767d3 100644 --- a/web/includes/Storage.php +++ b/web/includes/Storage.php @@ -58,6 +58,13 @@ class Storage extends ZM_Object { return $this->{'Events'}; } + public function EventCount() { + if ( (! property_exists($this, 'EventCount')) or (!$this->{'EventCount'}) ) { + $this->{'EventCount'} = dbFetchOne('SELECT COUNT(*) AS EventCount FROM Events WHERE StorageId=?', 'EventCount', array($this->Id())); + } + return $this->{'EventCount'}; + } + public function disk_usage_percent() { $path = $this->Path(); if ( ! $path ) { diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index 0a0d99286..a5aead8ca 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -278,8 +278,8 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $ 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()) ?> - Events()).' using '.human_filesize($Storage->event_disk_space()) ?> - Events()) or !$canEdit ) { ?> disabled="disabled"Events()) ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/> + EventCount().' using '.human_filesize($Storage->event_disk_space()) ?> + EventCount() or !$canEdit ) { ?> disabled="disabled"Eventount() ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/> From 91acb775eb623e0b6e1949faef463e4fa6d93c86 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 13:43:14 -0500 Subject: [PATCH 25/37] Fix Eventount to EventCount --- web/skins/classic/views/options.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index a5aead8ca..82692fbaf 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -279,7 +279,7 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*',GLOB_ONLYDIR)) as $ Id(), 'zmStorage', 'storage', validHtmlStr($Storage->Server()->Name()), $canEdit ) ?> disk_used_space()) . ' of ' . human_filesize($Storage->disk_total_space()) ?> EventCount().' using '.human_filesize($Storage->event_disk_space()) ?> - EventCount() or !$canEdit ) { ?> disabled="disabled"Eventount() ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/> + EventCount() or !$canEdit ) { ?> disabled="disabled"EventCount() ? ' title="Can\'t delete as long as there are events stored here."' : ''?>/> From 9036b6db77350c6741a492fcddbafd48ea05ade5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 16:17:39 -0500 Subject: [PATCH 26/37] fix typo --- web/includes/Event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Event.php b/web/includes/Event.php index 2ed20f95e..7e038397a 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -47,7 +47,7 @@ class Event extends ZM_Object { return ZM_Object::_find_one(get_class(), $parameters, $options); } - public static function clear_cahce() { + public static function clear_cache() { return ZM_Object::_clear_cache(get_class()); } From d7dc7cdc47ac4f69e0c4dcc26c16bc85746cb1dd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 16:18:01 -0500 Subject: [PATCH 27/37] Add ServerId to database log entries in php --- web/includes/logger.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web/includes/logger.php b/web/includes/logger.php index 7404891b6..fec205591 100644 --- a/web/includes/logger.php +++ b/web/includes/logger.php @@ -387,7 +387,7 @@ class Logger { if ( $this->hasTerm ) print($message."\n"); else - print(preg_replace("/\n/", '
', htmlspecialchars($message) ).'
'); + print(preg_replace("/\n/", '
', htmlspecialchars($message)).'
'); } if ( $level <= $this->fileLevel ) { @@ -410,9 +410,10 @@ class Logger { if ( $level <= $this->databaseLevel ) { try { global $dbConn; - $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )'; + $sql = 'INSERT INTO `Logs` ( `TimeKey`, `Component`, `ServerId`, `Pid`, `Level`, `Code`, `Message`, `File`, `Line` ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? )'; $stmt = $dbConn->prepare($sql); - $result = $stmt->execute(array(sprintf('%d.%06d', $time['sec'], $time['usec']), $this->id, getmypid(), $level, $code, $string, $file, $line)); + $result = $stmt->execute(array(sprintf('%d.%06d', $time['sec'], $time['usec']), $this->id, + (defined('ZM_SERVER_ID') ? ZM_SERVER_ID : null), getmypid(), $level, $code, $string, $file, $line)); } catch(PDOException $ex) { $this->databaseLevel = self::NOLOG; Error("Can't write log entry '$sql': ". $ex->getMessage()); From e4ba1fd432ffc4286d68771ca9b58456ab3910e9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 17:16:15 -0500 Subject: [PATCH 28/37] fix restarting zmcontrol on remote servers by passing object=filter as well --- web/includes/Filter.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/web/includes/Filter.php b/web/includes/Filter.php index 2ecf7b61e..8bccf3860 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -115,13 +115,17 @@ class Filter extends ZM_Object { public function control($command, $server_id=null) { $Servers = $server_id ? Server::find(array('Id'=>$server_id)) : Server::find(array('Status'=>'Running')); - if ( !count($Servers) and !$server_id ) { - # This will be the non-multi-server case - $Servers = array(new Server()); + if ( !count($Servers) ) { + if ( !$server_id ) { + # This will be the non-multi-server case + $Servers = array(new Server()); + } else { + Warning("Server not found for id $server_id"); + } } foreach ( $Servers as $Server ) { - if ( !defined('ZM_SERVER_ID') or !$Server->Id() or ZM_SERVER_ID==$Server->Id() ) { + if ( (!defined('ZM_SERVER_ID')) or (!$Server->Id()) or (ZM_SERVER_ID==$Server->Id()) ) { # Local Logger::Debug("Controlling filter locally $command for server ".$Server->Id()); daemonControl($command, 'zmfilter.pl', '--filter_id='.$this->{'Id'}.' --daemon'); @@ -139,7 +143,7 @@ class Filter extends ZM_Object { $url = '?user='.$_SESSION['username']; } } - $url .= '&view=filter&action=control&command='.$command.'&Id='.$this->Id().'&ServerId='.$Server->Id(); + $url .= '&view=filter&object=filter&action=control&command='.$command.'&Id='.$this->Id().'&ServerId='.$Server->Id(); Logger::Debug("sending command to $url"); $data = array(); if ( defined('ZM_ENABLE_CSRF_MAGIC') ) { From 02e9096d2b50c5c867e9c70acd0f5a5b16b5f6dc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 13 Jan 2020 17:32:57 -0500 Subject: [PATCH 29/37] When saving an existing Filter and we are unchecking Background, need to stop the filter before saving. Remove dead code --- web/includes/actions/filter.php | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/web/includes/actions/filter.php b/web/includes/actions/filter.php index ae6bf3ddc..ac2435302 100644 --- a/web/includes/actions/filter.php +++ b/web/includes/actions/filter.php @@ -64,35 +64,12 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) { $_REQUEST['filter']['Background'] = empty($_REQUEST['filter']['Background']) ? 0 : 1; $_REQUEST['filter']['Concurrent'] = empty($_REQUEST['filter']['Concurrent']) ? 0 : 1; $changes = $filter->changes($_REQUEST['filter']); - ZM\Logger::Debug("Changes: " . print_r($changes,true)); - - if ( 0 ) { - $sql .= ', Query = '.dbEscape(jsonEncode($_REQUEST['filter']['Query'])); - $sql .= ', AutoArchive = '.(!empty($_REQUEST['filter']['AutoArchive']) ? 1 : 0); - $sql .= ', AutoVideo = '. ( !empty($_REQUEST['filter']['AutoVideo']) ? 1 : 0); - $sql .= ', AutoUpload = '. ( !empty($_REQUEST['filter']['AutoUpload']) ? 1 : 0); - $sql .= ', AutoEmail = '. ( !empty($_REQUEST['filter']['AutoEmail']) ? 1 : 0); - $sql .= ', AutoMessage = '. ( !empty($_REQUEST['filter']['AutoMessage']) ? 1 : 0); - $sql .= ', AutoExecute = '. ( !empty($_REQUEST['filter']['AutoExecute']) ? 1 : 0); - $sql .= ', AutoExecuteCmd = '.dbEscape($_REQUEST['filter']['AutoExecuteCmd']); - $sql .= ', AutoDelete = '. ( !empty($_REQUEST['filter']['AutoDelete']) ? 1 : 0); - if ( !empty($_REQUEST['filter']['AutoMove']) ? 1 : 0) { - $sql .= ', AutoMove = 1, AutoMoveTo='. validInt($_REQUEST['filter']['AutoMoveTo']); - } else { - $sql .= ', AutoMove = 0'; - } - $sql .= ', UpdateDiskSpace = '. ( !empty($_REQUEST['filter']['UpdateDiskSpace']) ? 1 : 0); - $sql .= ', Background = '. ( !empty($_REQUEST['filter']['Background']) ? 1 : 0); - $sql .= ', Concurrent = '. ( !empty($_REQUEST['filter']['Concurrent']) ? 1 : 0); - } + ZM\Logger::Debug('Changes: ' . print_r($changes,true)); if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) { - if ( 0 ) { - dbQuery('UPDATE Filters SET '.$sql.' WHERE Id=?', array($_REQUEST['Id'])); - } - $filter->save($changes); if ( $filter->Background() ) $filter->control('stop'); + $filter->save($changes); } else { if ( $action == 'execute' ) { From 8b375de455e576b0c50f294dc29422409634507a Mon Sep 17 00:00:00 2001 From: Javier Gonzalez Date: Wed, 15 Jan 2020 20:31:05 +0100 Subject: [PATCH 30/37] Avoid duplicate Monitors in API --- web/api/app/Controller/MonitorsController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php index 789307795..92114a558 100644 --- a/web/api/app/Controller/MonitorsController.php +++ b/web/api/app/Controller/MonitorsController.php @@ -61,7 +61,8 @@ class MonitorsController extends AppController { 'Groups_Monitors.MonitorId = Monitor.Id', ), ), - ) + ), + 'group' => '`Monitor`.`Id`', ); $monitors = $this->Monitor->find('all',$find_array); $this->set(array( From d4bc0bf72bf90983bb06818f66ad6b9ff4100360 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jan 2020 17:31:06 -0500 Subject: [PATCH 31/37] bump version for release to 1.34.0 --- db/zm_update-1.34.0.sql | 5 +++++ distros/redhat/zoneminder.spec | 2 +- version | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 db/zm_update-1.34.0.sql diff --git a/db/zm_update-1.34.0.sql b/db/zm_update-1.34.0.sql new file mode 100644 index 000000000..b8bd3e4ed --- /dev/null +++ b/db/zm_update-1.34.0.sql @@ -0,0 +1,5 @@ +-- +-- This updates a 1.33.16 database to 1.34.0 +-- +-- No changes required +-- diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 6715f7b26..d083bb244 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -28,7 +28,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.33.16 +Version: 1.34.0 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/version b/version index c0bd57583..2b17ffd50 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.33.16 +1.34.0 From 09f229883838eca2b5732b1ee10017c39119cacb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 15 Jan 2020 19:02:40 -0500 Subject: [PATCH 32/37] return empty array instead of nothing in probeNetwork --- web/skins/classic/views/monitorprobe.php | 52 ++++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/web/skins/classic/views/monitorprobe.php b/web/skins/classic/views/monitorprobe.php index 8fb626516..9cab32b3e 100644 --- a/web/skins/classic/views/monitorprobe.php +++ b/web/skins/classic/views/monitorprobe.php @@ -247,18 +247,18 @@ function probeNetwork() { $arp_command = ZM_PATH_ARP; $result = explode(' ', $arp_command); if ( !is_executable($result[0]) ) { - ZM\Error("ARP compatible binary not found or not executable by the web user account. Verify ZM_PATH_ARP points to a valid arp tool."); - return; + ZM\Error('ARP compatible binary not found or not executable by the web user account. Verify ZM_PATH_ARP points to a valid arp tool.'); + return $cameras; } $result = exec(escapeshellcmd($arp_command), $output, $status); if ( $status ) { ZM\Error("Unable to probe network cameras, status is '$status'"); - return; + return $cameras; } $monitors = array(); - foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type = 'Remote' ORDER BY Host") as $monitor ) { + foreach ( dbFetchAll("SELECT `Id`, `Name`, `Host` FROM `Monitors` WHERE `Type` = 'Remote' ORDER BY `Host`") as $monitor ) { if ( preg_match('/^(.+)@(.+)$/', $monitor['Host'], $matches) ) { //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."
"; $monitors[gethostbyname($matches[2])] = $monitor; @@ -277,29 +277,29 @@ function probeNetwork() { '78:a5:dd' => array('type'=>'Wansview','probeFunc'=>'probeWansview') ); - foreach ( $output as $line ) { - if ( !preg_match('/(\d+\.\d+\.\d+\.\d+).*(([0-9a-f]{2}:){5})/', $line, $matches) ) - continue; - $ip = $matches[1]; - $host = $ip; - $mac = $matches[2]; - //echo "I:$ip, H:$host, M:$mac
"; - $macRoot = substr($mac,0,8); - if ( isset($macBases[$macRoot]) ) { - $macBase = $macBases[$macRoot]; - $camera = call_user_func($macBase['probeFunc'], $ip); - $sourceDesc = base64_encode(serialize($camera['monitor'])); - $sourceString = $camera['model'].' @ '.$host; - if ( isset($monitors[$ip]) ) { - $monitor = $monitors[$ip]; - $sourceString .= ' ('.$monitor['Name'].')'; - } else { - $sourceString .= ' - '.translate('Available'); - } - $cameras[$sourceDesc] = $sourceString; + foreach ( $output as $line ) { + if ( !preg_match('/(\d+\.\d+\.\d+\.\d+).*(([0-9a-f]{2}:){5})/', $line, $matches) ) + continue; + $ip = $matches[1]; + $host = $ip; + $mac = $matches[2]; + //echo "I:$ip, H:$host, M:$mac
"; + $macRoot = substr($mac,0,8); + if ( isset($macBases[$macRoot]) ) { + $macBase = $macBases[$macRoot]; + $camera = call_user_func($macBase['probeFunc'], $ip); + $sourceDesc = base64_encode(serialize($camera['monitor'])); + $sourceString = $camera['model'].' @ '.$host; + if ( isset($monitors[$ip]) ) { + $monitor = $monitors[$ip]; + $sourceString .= ' ('.$monitor['Name'].')'; + } else { + $sourceString .= ' - '.translate('Available'); } - } # end foreach output line - return $cameras; + $cameras[$sourceDesc] = $sourceString; + } + } # end foreach output line + return $cameras; } # end function probeNetwork() $cameras = array(); From 6a43c2deb5e6b752eba60382b6d26885d613c7f9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 16 Jan 2020 14:17:40 -0500 Subject: [PATCH 33/37] fix zoom_range to zoomout_range --- web/skins/classic/views/js/timeline.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/timeline.js b/web/skins/classic/views/js/timeline.js index 0b4715f75..8d3f01d4c 100644 --- a/web/skins/classic/views/js/timeline.js +++ b/web/skins/classic/views/js/timeline.js @@ -184,7 +184,7 @@ function tlZoomBounds( minTime, maxTime ) { } function tlZoomOut() { - location.replace('?view='+currentView+filterQuery+'&midTime='+midTime+'&range='+zoom_range); + location.replace('?view='+currentView+filterQuery+'&midTime='+midTime+'&range='+zoomout_range); } function tlPanLeft() { From 74b3ad6dd9a6e7bed2566c738f472fe4581d4b8f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 16 Jan 2020 14:33:37 -0500 Subject: [PATCH 34/37] add options help for HWACCEL options --- web/lang/en_gb.php | 8 ++++++++ web/skins/classic/views/monitor.php | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index a6f2fa488..ad4911a4d 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -981,6 +981,14 @@ $OLANG = array( "loglevel=debug" Set verbosity of FFmpeg (quiet, panic, fatal, error, warning, info, verbose, debug) ' ), + 'OPTIONS_DECODERHWACCELNAME' => array( + 'Help' => ' + This is equivalent to the ffmpeg -hwaccel command line option. With intel graphics support, use "vaapi". For NVIDIA cuda support use "cuda". To check for support, run ffmpeg -hwaccels on the command line.' + ), + 'OPTIONS_DECODERHWACCELDEVICE' => array( + 'Help' => ' + This is equivalent to the ffmpeg -hwaccel_device command line option. You should only have to specify this if you have multiple GPUs. A typical value for Intel VAAPI would be /dev/dri/renderD128.' + ), 'OPTIONS_RTSPTrans' => array( 'Help' => ' This sets the RTSP Transport Protocol for FFmpeg.~~ diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index fefeed34a..055a955fa 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -831,13 +831,13 @@ include('_monitor_source_nvsocket.php'); ?> - () + () - () + () From 4f2df830a828b8f073388f3aa59da27f8e9b2645 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 17 Jan 2020 09:17:05 -0500 Subject: [PATCH 35/37] fix inline js --- web/skins/classic/views/filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 425e914c9..1f696dd70 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -217,7 +217,7 @@ for ( $i=0; $i < count($terms); $i++ ) { } ?> 2 ) { echo htmlSelect("filter[Query][terms][$i][obr]", $obracketTypes, $term['obr']); } else { ?>  - + 'checkValue')); ?> Date: Fri, 17 Jan 2020 09:17:29 -0500 Subject: [PATCH 36/37] fix delTerm button not being enabled because it is a button now, not an input --- web/skins/classic/views/js/filter.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js index cfc284ab2..4444db954 100644 --- a/web/skins/classic/views/js/filter.js +++ b/web/skins/classic/views/js/filter.js @@ -30,7 +30,6 @@ function validateForm( form ) { function updateButtons(element) { var form = element.form; - console.log(element); if ( element.type == 'checkbox' && element.checked ) { form.elements['executeButton'].disabled = false; } else { @@ -105,6 +104,7 @@ function submitToEvents( element ) { form.action = thisUrl + '?view=events'; history.replaceState(null, null, '?view=filter&' + $j(form).serialize()); } + function submitToMontageReview( element ) { var form = element.form; form.action = thisUrl + '?view=montagereview'; @@ -143,12 +143,12 @@ function deleteFilter( element ) { } function parseRows(rows) { - for (var rowNum = 0; rowNum < rows.length; rowNum++) { //Each row is a term + for ( var rowNum = 0; rowNum < rows.length; rowNum++ ) { //Each row is a term var queryPrefix = 'filter[Query][terms]['; var inputTds = rows.eq(rowNum).children(); - if (rowNum == 0) inputTds.eq(0).html(' '); //Remove and from first term - if (rowNum > 0) { //add and/or to 1+ + if ( rowNum == 0 ) inputTds.eq(0).html(' '); //Remove and from first term + if ( rowNum > 0 ) { //add and/or to 1+ var cnjVal = inputTds.eq(0).children().val(); var conjSelect = $j('').attr('name', queryPrefix + rowNum + '][cnj]').attr('id', queryPrefix + rowNum + '][cnj]'); $j.each(conjTypes, function(i) { @@ -172,19 +172,19 @@ function parseRows(rows) { inputTds.eq(1).html(obrSelect).children().val(obrVal); //Set bracket contents and assign saved value inputTds.eq(5).html(cbrSelect).children().val(cbrVal); } else { - inputTds.eq(1).html(' '); //Blank if there aren't enough terms for brackets + inputTds.eq(1).html(' '); // Blank if there aren't enough terms for brackets inputTds.eq(5).html(' '); } - if (rows.length == 1) { - inputTds.eq(6).find(':input[value="-"]').prop('disabled', true); //enable/disable remove row button + if ( rows.length == 1 ) { + inputTds.eq(6).find('button[data-on-click-this="delTerm"]').prop('disabled', true); //enable/disable remove row button } else { - inputTds.eq(6).find(':input[value="-"]').prop('disabled', false); + inputTds.eq(6).find('button[data-on-click-this="delTerm"]').prop('disabled', false); } var attr = inputTds.eq(2).children().val(); - if ( attr == "Archived") { //Archived types + if ( attr == "Archived" ) { //Archived types inputTds.eq(3).html('equal to'); var archiveSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); for (var i = 0; i < archiveTypes.length; i++) { @@ -253,7 +253,7 @@ function parseRows(rows) { term[2] = rowNum; inputTds.eq(2).children().eq(0).attr('name', 'filter'+stringFilter(term)); inputTds.eq(2).children().eq(0).attr('id', 'filter'+stringFilter(term)); - }//End for each term/row + } // End for each term/row history.replaceState(null, null, '?view=filter&' + $j('#contentForm').serialize()); } From 86a2523498342d156868607e45bb8f7690110a4a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 17 Jan 2020 12:30:26 -0500 Subject: [PATCH 37/37] break up a long line, add some parenthesis to clarify logic --- web/includes/logger.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/includes/logger.php b/web/includes/logger.php index fec205591..2b5463dfb 100644 --- a/web/includes/logger.php +++ b/web/includes/logger.php @@ -362,10 +362,12 @@ class Logger { $code = self::$codes[$level]; $time = gettimeofday(); - $message = sprintf('%s.%06d %s[%d].%s [%s] [%s]', strftime('%x %H:%M:%S', $time['sec']), $time['usec'], $this->id, getmypid(), $code, $_SERVER['REMOTE_ADDR'], $string); + $message = sprintf('%s.%06d %s[%d].%s [%s] [%s]', + strftime('%x %H:%M:%S', $time['sec']), $time['usec'], + $this->id, getmypid(), $code, $_SERVER['REMOTE_ADDR'], $string); if ( is_null($file) ) { - if ( $this->useErrorLog || $this->databaseLevel > self::NOLOG ) { + if ( $this->useErrorLog || ($this->databaseLevel > self::NOLOG) ) { $backTrace = debug_backtrace(); $file = $backTrace[1]['file']; $line = $backTrace[1]['line'];