From e32b432fea28a524fa4805887035a32681a9ba59 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 11 Jun 2018 14:35:54 -0400 Subject: [PATCH 001/240] Always re-connect to the db on initialize --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 22 ++++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index f19d60bda..84e6c6012 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -439,16 +439,12 @@ sub databaseLevel { my $databaseLevel = shift; if ( defined($databaseLevel) ) { $databaseLevel = $this->limit($databaseLevel); - if ( $this->{databaseLevel} != $databaseLevel ) { - if ( $databaseLevel > NOLOG and $this->{databaseLevel} <= NOLOG ) { - if ( !$this->{dbh} ) { - $this->{dbh} = ZoneMinder::Database::zmDbConnect(); - } - } elsif ( $databaseLevel <= NOLOG && $this->{databaseLevel} > NOLOG ) { - undef($this->{dbh}); - } - $this->{databaseLevel} = $databaseLevel; + if ( $databaseLevel > NOLOG ) { + $this->{dbh} = ZoneMinder::Database::zmDbConnect(); + } elsif ( $databaseLevel <= NOLOG && $this->{databaseLevel} > NOLOG ) { + undef($this->{dbh}); } + $this->{databaseLevel} = $databaseLevel; } return $this->{databaseLevel}; } @@ -557,11 +553,13 @@ sub logPrint { if ( $level <= $this->{databaseLevel} ) { if ( ! ( $this->{dbh} and $this->{dbh}->ping() ) ) { $this->{sth} = undef; - if ( ! ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) { - #print(STDERR "Can't log to database: "); - $this->{databaseLevel} = NOLOG; + + my $databaseLevel = $this->{databaseLevel}; + $this->{databaseLevel} = NOLOG; + if ( ! ( $this->{dbh} = ZoneMinder::Database::zmDbConnect(1) ) ) { return; } + $this->{databaseLevel} = $databaseLevel; } my $sql = 'INSERT INTO Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NULL )'; From d5d206f00a103868ce31fe616bf9db2f65d7efef Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 11 Jun 2018 15:57:38 -0400 Subject: [PATCH 002/240] Force disconnect when reinitialize Logging --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 84e6c6012..3dc0592d4 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -440,7 +440,7 @@ sub databaseLevel { if ( defined($databaseLevel) ) { $databaseLevel = $this->limit($databaseLevel); if ( $databaseLevel > NOLOG ) { - $this->{dbh} = ZoneMinder::Database::zmDbConnect(); + $this->{dbh} = ZoneMinder::Database::zmDbConnect(1); } elsif ( $databaseLevel <= NOLOG && $this->{databaseLevel} > NOLOG ) { undef($this->{dbh}); } From f5026542f88149e33461b1fb3026a0a80bed8bd6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 11 Jun 2018 16:05:57 -0400 Subject: [PATCH 003/240] retest STDERR for terminal output on reinit. Simplify databaseLevel code to clear dbh always when not NOLOG. --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 3dc0592d4..4bf3c5a16 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -310,7 +310,7 @@ sub reinitialise { # Bit of a nasty hack to reopen connections to log files and the DB my $syslogLevel = $this->syslogLevel(); - $this->syslogLevel( NOLOG ); + $this->syslogLevel(NOLOG); $this->syslogLevel($syslogLevel) if $syslogLevel > NOLOG; my $logfileLevel = $this->fileLevel(); @@ -321,11 +321,10 @@ sub reinitialise { $this->databaseLevel(NOLOG); $this->databaseLevel($databaseLevel) if $databaseLevel > NOLOG; - my $screenLevel = $this->termLevel(); + $this->{hasTerm} = -t STDERR; + my $termLevel = $this->termLevel(); $this->termLevel(NOLOG); - $this->termLevel($screenLevel) if $screenLevel > NOLOG; - - $this->{sth} = undef; + $this->termLevel($termLevel) if $termLevel > NOLOG; } # Prevents undefined logging levels @@ -440,10 +439,11 @@ sub databaseLevel { if ( defined($databaseLevel) ) { $databaseLevel = $this->limit($databaseLevel); if ( $databaseLevel > NOLOG ) { - $this->{dbh} = ZoneMinder::Database::zmDbConnect(1); - } elsif ( $databaseLevel <= NOLOG && $this->{databaseLevel} > NOLOG ) { + $this->{dbh} = ZoneMinder::Database::zmDbConnect(); + } else { undef($this->{dbh}); } + $this->{sth} = undef; $this->{databaseLevel} = $databaseLevel; } return $this->{databaseLevel}; From 90e4c2632da458751c81cb6a4caae87feac4eeae Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Jul 2018 12:08:50 -0400 Subject: [PATCH 004/240] Use Server->Url() more,, moving the logic into Server->Url() --- web/includes/Event.php | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/web/includes/Event.php b/web/includes/Event.php index d7ce25dc4..9c00b3670 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -189,25 +189,19 @@ class Event { public function getStreamSrc( $args=array(), $querySep='&' ) { - $streamSrc = ZM_BASE_PROTOCOL.'://'; + $streamSrc = ''; if ( $this->Storage()->ServerId() ) { $Server = $this->Storage()->Server(); - $streamSrc .= $Server->Hostname(); - if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= ':'.(ZM_MIN_STREAMING_PORT+$this->{'MonitorId'}); - } } else if ( $this->Monitor()->ServerId() ) { # Assume that the server that recorded it has it $Server = $this->Monitor()->Server(); - $streamSrc .= $Server->Hostname(); - if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= ':'.(ZM_MIN_STREAMING_PORT+$this->{'MonitorId'}); - } - } else if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= $_SERVER['SERVER_NAME'].':'.(ZM_MIN_STREAMING_PORT+$this->{'MonitorId'}); } else { - $streamSrc .= $_SERVER['HTTP_HOST']; + $Server = new Server; } + $streamSrc .= $Server->Url( + ZM_MIN_STREAMING_PORT ? + ZM_MIN_STREAMING_PORT+$this->{'MonitorId'} : + null); if ( $this->{'DefaultVideo'} and $args['mode'] != 'jpeg' ) { $streamSrc .= ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php'; @@ -319,25 +313,19 @@ class Event { # The thumbnail is theoretically the image with the most motion. # We always store at least 1 image when capturing - $streamSrc = ZM_BASE_PROTOCOL.'://'; + $streamSrc = ''; if ( $this->Storage()->ServerId() ) { $Server = $this->Storage()->Server(); - $streamSrc .= $Server->Hostname(); - if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= ':'.(ZM_MIN_STREAMING_PORT+$this->{'MonitorId'}); - } } else if ( $this->Monitor()->ServerId() ) { + # Assume that the server that recorded it has it $Server = $this->Monitor()->Server(); - $streamSrc .= $Server->Hostname(); - if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= ':'.(ZM_MIN_STREAMING_PORT+$this->{'MonitorId'}); - } - - } else if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= $_SERVER['SERVER_NAME'].':'.(ZM_MIN_STREAMING_PORT+$this->{'MonitorId'}); } else { - $streamSrc .= $_SERVER['HTTP_HOST']; - } + $Server = new Server; + } + $streamSrc .= $Server->Url( + ZM_MIN_STREAMING_PORT ? + ZM_MIN_STREAMING_PORT+$this->{'MonitorId'} : + null); $streamSrc .= ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php'; $args['eid'] = $this->{'Id'}; From 34299aff2c94e15c76e2d59743b44da943175e4e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Jul 2018 12:09:10 -0400 Subject: [PATCH 005/240] Add PathPrefix to Servers Table --- db/zm_create.sql.in | 1 + 1 file changed, 1 insertion(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 83b75f768..d0482c479 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -556,6 +556,7 @@ DROP TABLE IF EXISTS `Servers`; CREATE TABLE `Servers` ( `Id` int(10) unsigned NOT NULL auto_increment, `Hostname` TEXT, + `PathPrefix` TEXT, `Name` varchar(64) NOT NULL default '', `State_Id` int(10) unsigned, `Status` enum('Unknown','NotRunning','Running') NOT NULL default 'Unknown', From 661876b9986ad2a567b8b9ee09fb3bbfab6ea861 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Jul 2018 12:09:29 -0400 Subject: [PATCH 006/240] Use Server->Url() more,, moving the logic into Server->Url() --- web/includes/Monitor.php | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 8fc69a9cd..bc9d92f8d 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -195,20 +195,13 @@ private $control_fields = array( } } - public function getStreamSrc( $args, $querySep='&' ) { + public function getStreamSrc($args, $querySep='&') { + + $streamSrc = $this->Server()->Url( + ZM_MIN_STREAMING_PORT ? + ZM_MIN_STREAMING_PORT+$this->{'Id'} : + null); - $streamSrc = ZM_BASE_PROTOCOL.'://'; - if ( isset($this->{'ServerId'}) and $this->{'ServerId'} ) { - $Server = new Server( $this->{'ServerId'} ); - $streamSrc .= $Server->Hostname(); - if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= ':'.(ZM_MIN_STREAMING_PORT+$this->{'Id'}); - } - } else if ( ZM_MIN_STREAMING_PORT ) { - $streamSrc .= $_SERVER['SERVER_NAME'].':'.(ZM_MIN_STREAMING_PORT+$this->{'Id'}); - } else { - $streamSrc .= $_SERVER['HTTP_HOST']; - } $streamSrc .= ZM_PATH_ZMS; $args['monitor'] = $this->{'Id'}; @@ -230,9 +223,9 @@ private $control_fields = array( $args['rand'] = time(); } - $streamSrc .= '?'.http_build_query( $args,'', $querySep ); + $streamSrc .= '?'.http_build_query($args,'', $querySep); - return( $streamSrc ); + return $streamSrc; } // end function getStreamSrc public function Width($new = null) { @@ -487,9 +480,10 @@ private $control_fields = array( $source = preg_replace( '/^.*\//', '', $this->{'Path'} ); } elseif ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) { $url_parts = parse_url( $this->{'Path'} ); - if ( ZM_WEB_FILTER_SOURCE == "Hostname" ) { # Filter out everything but the hostname + if ( ZM_WEB_FILTER_SOURCE == 'Hostname' ) { # Filter out everything but the hostname $source = $url_parts['host']; - } elseif ( ZM_WEB_FILTER_SOURCE == "NoCredentials" ) { # Filter out sensitive and common items + } elseif ( ZM_WEB_FILTER_SOURCE == 'NoCredentials' ) { + # Filter out sensitive and common items unset($url_parts['user']); unset($url_parts['pass']); #unset($url_parts['scheme']); From 62f45b430e8b463b4cfadeff026ffa5a967121c0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Jul 2018 12:09:57 -0400 Subject: [PATCH 007/240] Add PathPrefix and use it in Url. Make Url() smarter so it can do more of the heavy lifting. --- web/includes/Server.php | 114 ++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/web/includes/Server.php b/web/includes/Server.php index d76984598..591b26f90 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -1,24 +1,26 @@ null, - 'Name' => '', - 'Hostname' => '', - 'zmaudit' => 1, - 'zmstats' => 1, - 'zmtrigger' => 0, + 'Id' => null, + 'Name' => '', + 'Hostname' => '', + 'PathPrefix' => '/zm', + 'zmaudit' => 1, + 'zmstats' => 1, + 'zmtrigger' => 0, ); - public function __construct( $IdOrRow = NULL ) { + + public function __construct($IdOrRow = NULL) { $row = NULL; if ( $IdOrRow ) { - if ( is_integer( $IdOrRow ) or ctype_digit( $IdOrRow ) ) { - $row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) ); - if ( ! $row ) { - Error("Unable to load Server record for Id=" . $IdOrRow ); + if ( is_integer($IdOrRow) or ctype_digit($IdOrRow) ) { + $row = dbFetchOne('SELECT * FROM Servers WHERE Id=?', NULL, array($IdOrRow)); + if ( !$row ) { + Error('Unable to load Server record for Id='.$IdOrRow); } - } elseif ( is_array( $IdOrRow ) ) { + } elseif ( is_array($IdOrRow) ) { $row = $IdOrRow; } } # end if isset($IdOrRow) @@ -27,11 +29,12 @@ class Server { $this->{$k} = $v; } } else { - $this->{'Name'} = ''; - $this->{'Hostname'} = ''; + # Set defaults + foreach ( $this->defaults as $k => $v ) $this->{$k} = $v; } } - public static function find_all( $parameters = null, $options = null ) { + + public static function find_all($parameters = null, $options = null) { $filters = array(); $sql = 'SELECT * FROM Servers '; $values = array(); @@ -42,9 +45,9 @@ class Server { foreach ( $parameters as $field => $value ) { if ( $value == null ) { $fields[] = $field.' IS NULL'; - } else if ( is_array( $value ) ) { + } else if ( is_array($value) ) { $func = function(){return '?';}; - $fields[] = $field.' IN ('.implode(',', array_map( $func, $value ) ). ')'; + $fields[] = $field.' IN ('.implode(',', array_map($func, $value) ). ')'; $values += $value; } else { @@ -52,10 +55,10 @@ class Server { $values[] = $value; } } - $sql .= implode(' AND ', $fields ); + $sql .= implode(' AND ', $fields); } if ( $options and isset($options['order']) ) { - $sql .= ' ORDER BY ' . $options['order']; + $sql .= ' ORDER BY ' . $options['order']; } $result = dbQuery($sql, $values); $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Server'); @@ -65,20 +68,19 @@ class Server { return $filters; } - public function Url() { - if ( $this->Id() ) { - return ZM_BASE_PROTOCOL . '://'. $this->Hostname(); - } else { - return ZM_BASE_PROTOCOL . '://'. $_SERVER['SERVER_NAME']; - return ''; - } - } - public function Hostname() { - if ( isset( $this->{'Hostname'} ) and ( $this->{'Hostname'} != '' ) ) { - return $this->{'Hostname'}; - } - return $this->{'Name'}; - } + public function Url($port=null) { + return ZM_BASE_PROTOCOL.'://'.$this->Hostname().($port ? ':'.$port : '').$this->{'PathPrefix'}; + } + + public function Hostname() { + if ( isset( $this->{'Hostname'}) and ( $this->{'Hostname'} != '' ) ) { + return $this->{'Hostname'}; + } else if ( $this->Id() ) { + return $this->{'Name'}; + } + return $_SERVER['SERVER_NAME']; + } + public function __call($fn, array $args){ if ( count($args) ) { $this->{$fn} = $args[0]; @@ -86,49 +88,49 @@ class Server { if ( array_key_exists($fn, $this) ) { return $this->{$fn}; } else { - if ( array_key_exists( $fn, $this->defaults ) ) { + if ( array_key_exists($fn, $this->defaults) ) { return $this->defaults{$fn}; } else { $backTrace = debug_backtrace(); $file = $backTrace[1]['file']; $line = $backTrace[1]['line']; - Warning( "Unknown function call Server->$fn from $file:$line" ); + Warning("Unknown function call Server->$fn from $file:$line"); } } } - public static function find( $parameters = array(), $limit = NULL ) { + public static function find($parameters = array(), $limit = NULL) { $sql = 'SELECT * FROM Servers'; $values = array(); if ( sizeof($parameters) ) { - $sql .= ' WHERE ' . implode( ' AND ', array_map( + $sql .= ' WHERE ' . implode(' AND ', array_map( function($v){ return $v.'=?'; }, - array_keys( $parameters ) - ) ); - $values = array_values( $parameters ); + array_keys($parameters) + )); + $values = array_values($parameters); } - if ( is_integer( $limit ) or ctype_digit( $limit ) ) { - $sql .= ' LIMIT ' . $limit; - } else { - $backTrace = debug_backtrace(); - $file = $backTrace[1]['file']; - $line = $backTrace[1]['line']; - Error("Invalid value for limit($limit) passed to Server::find from $file:$line"); - return; - } - $results = dbFetchAll( $sql, NULL, $values ); + if ( is_integer($limit) or ctype_digit($limit) ) { + $sql .= ' LIMIT ' . $limit; + } else { + $backTrace = debug_backtrace(); + $file = $backTrace[1]['file']; + $line = $backTrace[1]['line']; + Error("Invalid value for limit($limit) passed to Server::find from $file:$line"); + return; + } + $results = dbFetchAll($sql, NULL, $values); if ( $results ) { - return array_map( function($id){ return new Server($id); }, $results ); + return array_map(function($id){ return new Server($id); }, $results); } } - public static function find_one( $parameters = array() ) { - $results = Server::find( $parameters, 1 ); - if ( ! sizeof( $results ) ) { + public static function find_one($parameters = array()) { + $results = Server::find($parameters, 1); + if ( !sizeof($results) ) { return; } return $results[0]; } -} +} # end class Server ?> From d051342e9f629e8904e10763b517802c4a464b11 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Jul 2018 12:10:29 -0400 Subject: [PATCH 008/240] Add PathPrefix --- web/skins/classic/views/server.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/server.php b/web/skins/classic/views/server.php index ae78d622f..2791a3f64 100644 --- a/web/skins/classic/views/server.php +++ b/web/skins/classic/views/server.php @@ -24,7 +24,7 @@ if ( !canEdit( 'System' ) ) { } if ( $_REQUEST['id'] ) { - if ( !($newServer = dbFetchOne( 'SELECT * FROM Servers WHERE Id = ?', NULL, ARRAY($_REQUEST['id'])) ) ) { + if ( !($newServer = dbFetchOne('SELECT * FROM Servers WHERE Id = ?', NULL, ARRAY($_REQUEST['id']))) ) { $view = 'error'; return; } @@ -32,6 +32,7 @@ if ( $_REQUEST['id'] ) { $newServer = array(); $newServer['Name'] = translate('NewServer'); $newServer['Hostname'] = ''; + $newServer['PathPrefix'] = '/zm'; $newServer['zmstats'] = ''; $newServer['zmaudit'] = ''; $newServer['zmtrigger'] = ''; @@ -39,7 +40,7 @@ if ( $_REQUEST['id'] ) { $focusWindow = true; -xhtmlHeaders(__FILE__, translate('Server').' - '.$newServer['Name'] ); +xhtmlHeaders(__FILE__, translate('Server').' - '.$newServer['Name']); ?>
@@ -47,7 +48,7 @@ xhtmlHeaders(__FILE__, translate('Server').' - '.$newServer['Name'] );

-
+ @@ -61,6 +62,10 @@ xhtmlHeaders(__FILE__, translate('Server').' - '.$newServer['Name'] ); + + + + From acab621f2c43369ae3d01ec0df7c1847152afae5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Jul 2018 12:18:14 -0400 Subject: [PATCH 009/240] bump version for db update --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 856307b22..6701dcb1c 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.44 +1.31.45 From ebe55cf6a45762ee49fb0ac5d4ad6f99770fbc76 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 Jul 2018 14:10:06 -0400 Subject: [PATCH 010/240] Include new Server.js --- web/js/Server.js | 12 ++++++++++++ web/skins/classic/includes/functions.php | 2 ++ 2 files changed, 14 insertions(+) create mode 100644 web/js/Server.js diff --git a/web/js/Server.js b/web/js/Server.js new file mode 100644 index 000000000..6e3254f65 --- /dev/null +++ b/web/js/Server.js @@ -0,0 +1,12 @@ +class Server { + constructor(json) { + for( var k in json ) { + this[k] = json[k]; + } + } + url(port=0){ + return location.protocol+'//'+this.Hostname+ + (port ? ':'+port : '') + + ( ( this.PathPrefix && this.PathPrefix != 'null') ? this.PathPrefix : ''); + } +}; diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 66243daf3..e39df3ebe 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -119,6 +119,8 @@ echo output_link_if_exists( array( + + From abeafe9ba6c26bfc44c8f7123e2fe073d2007a4d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 12 Nov 2018 15:43:03 -0500 Subject: [PATCH 088/240] fix log export. minTime and maxTime were being cleared by the regexp to detect sub second time. Also use ZM_DIR_EXPORTS instead of ZM_PATH_SWAP --- web/ajax/log.php | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/web/ajax/log.php b/web/ajax/log.php index f0703f871..fca79fda4 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -164,14 +164,23 @@ switch ( $_REQUEST['task'] ) { $where = array(); $values = array(); if ( $minTime ) { - preg_match('/(.+)(\.\d+)/', $minTime, $matches); - $minTime = strtotime($matches[1]).$matches[2]; + Logger::Debug("MinTime: $minTime"); + if ( preg_match('/(.+)(\.\d+)/', $minTime, $matches) ) { + # This handles sub second precision + $minTime = strtotime($matches[1]).$matches[2]; + Logger::Debug("MinTime: $minTime"); + } else { + $minTime = strtotime($minTime); + } $where[] = 'TimeKey >= ?'; $values[] = $minTime; } if ( $maxTime ) { - preg_match('/(.+)(\.\d+)/', $maxTime, $matches); - $maxTime = strtotime($matches[1]).$matches[2]; + if ( preg_match('/(.+)(\.\d+)/', $maxTime, $matches) ) { + $maxTime = strtotime($matches[1]).$matches[2]; + } else { + $maxTime = strtotime($maxTime); + } $where[] = 'TimeKey <= ?'; $values[] = $maxTime; } @@ -209,8 +218,15 @@ switch ( $_REQUEST['task'] ) { } $exportKey = substr(md5(rand()),0,8); $exportFile = "zm-log.$exportExt"; - $exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt"; - if ( !($exportFP = fopen( $exportPath, "w" )) ) + if ( ! file_exists(ZM_DIR_EXPORTS) ) { + Logger::Debug('Creating ' . ZM_DIR_EXPORTS); + if ( ! mkdir(ZM_DIR_EXPORTS) ) { + Fatal("Can't create exports dir at '".ZM_DIR_EXPORTS."'"); + } + } + $exportPath = ZM_DIR_EXPORTS."/zm-log-$exportKey.$exportExt"; + Logger::Debug("Exporting to $exportPath"); + if ( !($exportFP = fopen($exportPath, 'w')) ) Fatal("Unable to open log export file $exportPath"); $logs = array(); foreach ( dbFetchAll($sql, NULL, $values) as $log ) { @@ -218,6 +234,8 @@ switch ( $_REQUEST['task'] ) { $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; $logs[] = $log; } + Logger::Debug(count($logs)." lines being exported by $sql " . implode(',',$values)); + switch( $format ) { case 'text' : { @@ -390,7 +408,7 @@ switch ( $_REQUEST['task'] ) { } $exportFile = "zm-log.$exportExt"; - $exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt"; + $exportPath = ZM_DIR_EXPORTS."/zm-log-$exportKey.$exportExt"; header('Pragma: public'); header('Expires: 0'); From 993da131f1b07940da5f8b91260d10cabe3eef6b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Nov 2018 10:29:19 -0500 Subject: [PATCH 089/240] tidy up and use Error instead of Carp::croak --- scripts/ZoneMinder/lib/ZoneMinder/Database.pm | 108 +++++++++++------- 1 file changed, 69 insertions(+), 39 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm index b1fca1d16..dcc797bd4 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm @@ -41,17 +41,18 @@ our @ISA = qw(Exporter ZoneMinder::Base); # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. our %EXPORT_TAGS = ( - 'functions' => [ qw( + functions => [ qw( zmDbConnect zmDbDisconnect zmDbGetMonitors zmDbGetMonitor zmDbGetMonitorAndControl + zmDbDo ) ] ); push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; -our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } ); our @EXPORT = qw(); @@ -66,8 +67,6 @@ our $VERSION = $ZoneMinder::Base::VERSION; use ZoneMinder::Logger qw(:all); use ZoneMinder::Config qw(:all); -use Carp; - our $dbh = undef; sub zmDbConnect { @@ -93,7 +92,7 @@ sub zmDbConnect { my $sslOptions = ''; if ( $Config{ZM_DB_SSL_CA_CERT} ) { - $sslOptions = ';'.join(';', + $sslOptions = join(';','', 'mysql_ssl=1', 'mysql_ssl_ca_file='.$Config{ZM_DB_SSL_CA_CERT}, 'mysql_ssl_client_key='.$Config{ZM_DB_SSL_CLIENT_KEY}, @@ -102,8 +101,9 @@ sub zmDbConnect { } eval { - $dbh = DBI->connect( 'DBI:mysql:database='.$Config{ZM_DB_NAME} - .$socket . $sslOptions . ($options?';'.join(';', map { $_.'='.$$options{$_} } keys %{$options} ) : '') + $dbh = DBI->connect( + 'DBI:mysql:database='.$Config{ZM_DB_NAME} + .$socket . $sslOptions . ($options?join(';', '', map { $_.'='.$$options{$_} } keys %{$options} ) : '') , $Config{ZM_DB_USER} , $Config{ZM_DB_PASS} ); @@ -125,7 +125,7 @@ sub zmDbConnect { sub zmDbDisconnect { if ( defined( $dbh ) ) { - $dbh->disconnect(); + $dbh->disconnect() or Error('Error disconnecting db? ' . $dbh->errstr()); $dbh = undef; } } @@ -141,7 +141,7 @@ sub zmDbGetMonitors { zmDbConnect(); my $function = shift || DB_MON_ALL; - my $sql = "select * from Monitors"; + my $sql = 'SELECT * FROM Monitors'; if ( $function ) { if ( $function == DB_MON_CAPT ) { @@ -156,26 +156,38 @@ sub zmDbGetMonitors { $sql .= " where Function = 'Nodect'"; } } - my $sth = $dbh->prepare_cached( $sql ) - or croak( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute() - or croak( "Can't execute '$sql': ".$sth->errstr() ); + my $sth = $dbh->prepare_cached( $sql ); + if ( ! $sth ) { + Error("Can't prepare '$sql': ".$dbh->errstr()); + return undef; + } + my $res = $sth->execute(); + if ( ! $res ) { + Error("Can't execute '$sql': ".$sth->errstr()); + return undef; + } my @monitors; while( my $monitor = $sth->fetchrow_hashref() ) { push( @monitors, $monitor ); } $sth->finish(); - return( \@monitors ); + return \@monitors; } sub zmSQLExecute { my $sql = shift; - - my $sth = $dbh->prepare_cached( $sql ) - or croak( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( @_ ) - or croak( "Can't execute '$sql': ".$sth->errstr() ); + + my $sth = $dbh->prepare_cached( $sql ); + if ( ! $sth ) { + Error("Can't prepare '$sql': ".$dbh->errstr()); + return undef; + } + my $res = $sth->execute( @_ ); + if ( ! $res ) { + Error("Can't execute '$sql': ".$sth->errstr()); + return undef; + } return 1; } @@ -185,17 +197,22 @@ sub zmDbGetMonitor { my $id = shift; if ( !defined($id) ) { - croak("Undefined id in zmDbgetMonitor"); + Error('Undefined id in zmDbgetMonitor'); return undef ; } my $sql = 'SELECT * FROM Monitors WHERE Id = ?'; - my $sth = $dbh->prepare_cached($sql) - or croak("Can't prepare '$sql': ".$dbh->errstr()); - my $res = $sth->execute($id) - or croak("Can't execute '$sql': ".$sth->errstr()); + my $sth = $dbh->prepare_cached($sql); + if ( !$sth ) { + Error("Can't prepare '$sql': ".$dbh->errstr()); + return undef; + } + my $res = $sth->execute($id); + if ( $res ) { + Error("Can't execute '$sql': ".$sth->errstr()); + return undef; + } my $monitor = $sth->fetchrow_hashref(); - return $monitor; } @@ -204,25 +221,28 @@ sub zmDbGetMonitorAndControl { my $id = shift; - return( undef ) if ( !defined($id) ); + return undef if !defined($id); - my $sql = "SELECT C.*,M.*,C.Protocol + my $sql = 'SELECT C.*,M.*,C.Protocol FROM Monitors as M INNER JOIN Controls as C on (M.ControlId = C.Id) - WHERE M.Id = ?" + WHERE M.Id = ?' ; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $id ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + my $sth = $dbh->prepare_cached($sql); + if ( !$sth ) { + Error("Can't prepare '$sql': ".$dbh->errstr()); + return undef; + } + my $res = $sth->execute( $id ); + if ( !$res ) { + Error("Can't execute '$sql': ".$sth->errstr()); + return undef; + } my $monitor = $sth->fetchrow_hashref(); - - return( $monitor ); + return $monitor; } sub start_transaction { - #my ( $caller, undef, $line ) = caller; -#$openprint::log->debug("Called start_transaction from $caller : $line"); my $d = shift; $d = $dbh if ! $d; my $ac = $d->{AutoCommit}; @@ -231,20 +251,29 @@ sub start_transaction { } # end sub start_transaction sub end_transaction { - #my ( $caller, undef, $line ) = caller; - #$openprint::log->debug("Called end_transaction from $caller : $line"); my ( $d, $ac ) = @_; if ( ! defined $ac ) { Error("Undefined ac"); } $d = $dbh if ! $d; if ( $ac ) { - #$log->debug("Committing"); $d->commit(); } # end if $d->{AutoCommit} = $ac; } # end sub end_transaction +# Basic execution of $dbh->do but with some pretty logging of the sql on error. +# Returns 1 on success, 0 on error +sub zmDbDo { + my $sql = shift; + if ( ! $dbh->do($sql, undef, @_) ) { + $sql =~ s/\?/'%s'/; + Error(sprintf("Failed $sql :", @_).$dbh->errstr()); + return 0; + } + return 1; +} + 1; __END__ @@ -266,6 +295,7 @@ zmDbDisconnect zmDbGetMonitors zmDbGetMonitor zmDbGetMonitorAndControl +zmDbDo =head1 AUTHOR From 31b0ed107d8209b5d4b178e5b3274217cf0a0f71 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Nov 2018 14:02:44 -0500 Subject: [PATCH 090/240] remove epadding2, to restore the 64bit alignment of startup_time. A proper fix instead of #2258 --- scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in | 1 - src/zm_monitor.h | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in index 2529c8786..7c5292720 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -161,7 +161,6 @@ our $mem_data = { format => { type=>'uint8', seq=>$mem_seq++ }, imagesize => { type=>'uint32', seq=>$mem_seq++ }, epadding1 => { type=>'uint32', seq=>$mem_seq++ }, - epadding2 => { type=>'uint32', seq=>$mem_seq++ }, startup_time => { type=>'time_t64', seq=>$mem_seq++ }, last_write_time => { type=>'time_t64', seq=>$mem_seq++ }, last_read_time => { type=>'time_t64', seq=>$mem_seq++ }, diff --git a/src/zm_monitor.h b/src/zm_monitor.h index b98f5953f..d7be9555e 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -127,24 +127,25 @@ protected: uint8_t format; /* +55 */ uint32_t imagesize; /* +56 */ uint32_t epadding1; /* +60 */ - uint32_t epadding2; /* +64 */ /* ** This keeps 32bit time_t and 64bit time_t identical and compatible as long as time is before 2038. ** Shared memory layout should be identical for both 32bit and 64bit and is multiples of 16. + ** Because startup_time is 64bit it may be aligned to a 64bit boundary. So it's offset SHOULD be a multiple + ** of 8. Add or delete epadding's to achieve this. */ - union { /* +68 */ + union { /* +64 */ time_t startup_time; /* When the zmc process started. zmwatch uses this to see how long the process has been running without getting any images */ uint64_t extrapad1; }; - union { /* +76 */ + union { /* +72 */ time_t last_write_time; uint64_t extrapad2; }; - union { /* +84 */ + union { /* +80 */ time_t last_read_time; uint64_t extrapad3; }; - uint8_t control_state[256]; /* +92 */ + uint8_t control_state[256]; /* +88 */ char alarm_cause[256]; From 798bf68df1ed1fef1031cc9a3595aabc2576e246 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Nov 2018 14:13:32 -0500 Subject: [PATCH 091/240] add function time_of_youngest_file to determine the youngest file in an event dir, so as to guess the starttime of the event. --- scripts/ZoneMinder/lib/ZoneMinder/Event.pm | 112 ++++++++++----------- 1 file changed, 52 insertions(+), 60 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 67cd850b9..5916f8cdb 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -320,11 +320,11 @@ sub GenerateVideo { my $file_size = 'S'.$size; push( @file_parts, $file_size ); } - my $video_file = "$video_name-".$file_parts[0]."-".$file_parts[1].".$format"; + my $video_file = join('-', $video_name, $file_parts[0], $file_parts[1] ).'.'.$format; if ( $overwrite || !-s $video_file ) { - Info( "Creating video file $video_file for event $self->{Id}\n" ); + Info("Creating video file $video_file for event $self->{Id}"); - my $frame_rate = sprintf( "%.2f", $self->{Frames}/$self->{FullLength} ); + my $frame_rate = sprintf('%.2f', $self->{Frames}/$self->{FullLength}); if ( $rate ) { if ( $rate != 1.0 ) { $frame_rate *= $rate; @@ -355,19 +355,19 @@ sub GenerateVideo { .$Config{ZM_FFMPEG_OUTPUT_OPTIONS} ." '$video_file' > ffmpeg.log 2>&1" ; - Debug( $command."\n" ); + Debug($command); my $output = qx($command); my $status = $? >> 8; if ( $status ) { - Error( "Unable to generate video, check $event_path/ffmpeg.log for details"); + Error("Unable to generate video, check $event_path/ffmpeg.log for details"); return; } - Info( "Finished $video_file\n" ); + Info("Finished $video_file"); return $event_path.'/'.$video_file; } else { - Info( "Video file $video_file already exists for event $self->{Id}\n" ); + Info("Video file $video_file already exists for event $self->{Id}"); return $event_path.'/'.$video_file; } return; @@ -375,57 +375,49 @@ sub GenerateVideo { sub delete { my $event = $_[0]; - if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartTime} ) ) { - my ( $caller, undef, $line ) = caller; - Warning("Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime} from $caller:$line\n"); - return; - } - if ( ! -e $event->Storage()->Path() ) { - Warning("Not deleting event because storage path doesn't exist"); - return; - } - Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime}\n"); - $ZoneMinder::Database::dbh->ping(); - $ZoneMinder::Database::dbh->begin_work(); - #$event->lock_and_load(); + my $in_zmaudit = ( $0 =~ 'zmaudit.pl$'); - { - my $sql = 'DELETE FROM Frames WHERE EventId=?'; - my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql) - or Error( "Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr() ); - my $res = $sth->execute($event->{Id}) - or Error( "Can't execute '$sql': ".$sth->errstr() ); - $sth->finish(); + if ( ! $in_zmaudit ) { + if ( ! ( $event->{Id} and $event->{MonitorId} and $event->{StartTime} ) ) { + # zmfilter shouldn't delete anything in an odd situation. zmaudit will though. + my ( $caller, undef, $line ) = caller; + Warning("$0 Can't Delete event $event->{Id} from Monitor $event->{MonitorId} StartTime:". + (defined($event->{StartTime})?$event->{StartTime}:'undef')." from $caller:$line"); + return; + } + if ( !($event->Storage()->Path() and -e $event->Storage()->Path()) ) { + Warning('Not deleting event because storage path doesn\'t exist'); + return; + } + } + + if ( $$event{Id} ) { + # Need to have an event Id if we are to delete from the db. + Info("Deleting event $event->{Id} from Monitor $event->{MonitorId} StartTime:$event->{StartTime}"); + $ZoneMinder::Database::dbh->ping(); + + $ZoneMinder::Database::dbh->begin_work(); + #$event->lock_and_load(); + + ZoneMinder::Database::zmDbDo('DELETE FROM Frames WHERE EventId=?', $$event{Id}); + if ( $ZoneMinder::Database::dbh->errstr() ) { + $ZoneMinder::Database::dbh->commit(); + return; + } + ZoneMinder::Database::zmDbDo('DELETE FROM Stats WHERE EventId=?', $$event{Id}); if ( $ZoneMinder::Database::dbh->errstr() ) { $ZoneMinder::Database::dbh->commit(); return; } - $sql = 'DELETE FROM Stats WHERE EventId=?'; - $sth = $ZoneMinder::Database::dbh->prepare_cached($sql) - or Error("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr()); - $res = $sth->execute($event->{Id}) - or Error("Can't execute '$sql': ".$sth->errstr()); - $sth->finish(); - if ( $ZoneMinder::Database::dbh->errstr() ) { - $ZoneMinder::Database::dbh->commit(); - return; - } + # Do it individually to avoid locking up the table for new events + ZoneMinder::Database::zmDbDo('DELETE FROM Events WHERE Id=?', $$event{Id}); + $ZoneMinder::Database::dbh->commit(); } -# Do it individually to avoid locking up the table for new events - { - my $sql = 'DELETE FROM Events WHERE Id=?'; - my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql) - or Error("Can't prepare '$sql': ".$ZoneMinder::Database::dbh->errstr()); - my $res = $sth->execute($event->{Id}) - or Error("Can't execute '$sql': ".$sth->errstr()); - $sth->finish(); - } - $ZoneMinder::Database::dbh->commit(); - if ( (! $Config{ZM_OPT_FAST_DELETE}) and $event->Storage()->DoDelete() ) { - $event->delete_files( ); + if ( ( $in_zmaudit or (!$Config{ZM_OPT_FAST_DELETE})) and $event->Storage()->DoDelete() ) { + $event->delete_files(); } else { Debug('Not deleting event files from '.$event->Path().' for speed.'); } @@ -434,11 +426,11 @@ sub delete { sub delete_files { my $event = shift; - my $Storage = @_ ? $_[0] : new ZoneMinder::Storage( $$event{StorageId} ); + my $Storage = @_ ? $_[0] : new ZoneMinder::Storage($$event{StorageId}); my $storage_path = $Storage->Path(); if ( ! $storage_path ) { - Error("Empty storage path when deleting files for event $$event{Id} with storage id $$event{StorageId} "); + Error("Empty storage path when deleting files for event $$event{Id} with storage id $$event{StorageId}"); return; } @@ -470,14 +462,14 @@ sub delete_files { if ( $bucket->delete_key($event_path) ) { $deleted = 1; } else { - Error("Failed to delete from S3:".$s3->err . ": " . $s3->errstr); + Error('Failed to delete from S3:'.$s3->err . ': ' . $s3->errstr); } }; Error($@) if $@; } - if ( ! $deleted ) { + if ( !$deleted ) { my $command = "/bin/rm -rf $storage_path/$event_path"; - ZoneMinder::General::executeShellCommand( $command ); + ZoneMinder::General::executeShellCommand($command); } } @@ -486,7 +478,7 @@ sub delete_files { Debug("Deleting link for Event $$event{Id} from $storage_path/$link_path."); if ( $link_path ) { ( $link_path ) = ( $link_path =~ /^(.*)$/ ); # De-taint - unlink($storage_path.'/'.$link_path) or Error( "Unable to unlink '$storage_path/$link_path': $!" ); + unlink($storage_path.'/'.$link_path) or Error("Unable to unlink '$storage_path/$link_path': $!"); } } } # end sub delete_files @@ -506,7 +498,7 @@ sub check_for_in_filesystem { if ( $path ) { if ( -e $path ) { my @files = glob "$path/*"; - Debug("Checking for files for event $_[0]{Id} at $path using glob $path/* found " . scalar @files . " files"); + Debug("Checking for files for event $_[0]{Id} at $path using glob $path/* found " . scalar @files . ' files'); return 1 if @files; } else { Warning("Path not found for Event $_[0]{Id} at $path"); @@ -577,7 +569,7 @@ sub MoveTo { if ( $$OldStorage{Id} != $$self{StorageId} ) { $ZoneMinder::Database::dbh->commit(); - return "Old Storage path changed, Event has moved somewhere else."; + return 'Old Storage path changed, Event has moved somewhere else.'; } $$self{Storage} = $NewStorage; @@ -621,11 +613,11 @@ Debug("Files to move @files"); Debug("Moving file $file to $NewPath"); my $size = -s $file; if ( ! $size ) { - Info("Not moving file with 0 size"); + Info('Not moving file with 0 size'); } my $file_contents = File::Slurp::read_file($file); if ( ! $file_contents ) { - die "Loaded empty file, but it had a size. Giving up"; + die 'Loaded empty file, but it had a size. Giving up'; } my $filename = $event_path.'/'.File::Basename::basename($file); @@ -633,7 +625,7 @@ Debug("Files to move @files"); die "Unable to add key for $filename"; } my $duration = time - $starttime; - Debug("PUT to S3 " . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . Number::Bytes::Human::format_bytes($duration?$size/$duration:$size) . '/sec'); + Debug('PUT to S3 ' . Number::Bytes::Human::format_bytes($size) . " in $duration seconds = " . Number::Bytes::Human::format_bytes($duration?$size/$duration:$size) . '/sec'); } # end foreach file. $moved = 1; From ca87936cd78e427511e57408460045b72ae0fef7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Nov 2018 14:13:41 -0500 Subject: [PATCH 092/240] add function time_of_youngest_file to determine the youngest file in an event dir, so as to guess the starttime of the event. --- scripts/zmaudit.pl.in | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index ebd56229e..7a5017fbd 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -384,7 +384,7 @@ MAIN: while( $loop ) { Debug("Checking for Medium Scheme Events under $$Storage{Path}/$monitor_dir"); { my @event_dirs = glob("$monitor_dir/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*"); - Debug(qq`glob("$monitor_dir/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*") returned ` . scalar @event_dirs . " entries." ); + Debug(qq`glob("$monitor_dir/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*") returned ` . scalar @event_dirs . ' entries.' ); foreach my $event_dir ( @event_dirs ) { if ( ! -d $event_dir ) { Debug( "$event_dir is not a dir. Skipping" ); @@ -403,6 +403,7 @@ MAIN: while( $loop ) { $$Event{RelativePath} = $event_dir; $Event->MonitorId( $monitor_dir ); $Event->StorageId( $Storage->Id() ); + $Event->StartTime( POSIX::strftime('%Y-%m-%d %H:%M:%S', gmtime(time_of_youngest_file($$Event{Path})) ) ); } # end foreach event } @@ -428,7 +429,7 @@ MAIN: while( $loop ) { } # end foreach event chdir( $Storage->Path() ); } # if USE_DEEP_STORAGE - Debug( 'Got '.int(keys(%$fs_events))." filesystem events for monitor $monitor_dir\n" ); + Debug( 'Got '.int(keys(%$fs_events))." filesystem events for monitor $monitor_dir" ); delete_empty_subdirs($$Storage{Path}.'/'.$monitor_dir); } # end foreach monitor @@ -446,7 +447,7 @@ MAIN: while( $loop ) { next; } my @event_ids = keys %$fs_events; - Debug("Have " .scalar @event_ids . " events for monitor $monitor_id"); + Debug('Have ' .scalar @event_ids . " events for monitor $monitor_id"); foreach my $fs_event_id ( sort { $a <=> $b } keys %$fs_events ) { @@ -490,7 +491,11 @@ MAIN: while( $loop ) { } } } # end foreach Storage Area - redo MAIN if ( $cleaned ); + + if ( $cleaned ) { + Debug("Events were deleted, starting again."); + redo MAIN; + } $cleaned = 0; my $deleteMonitorSql = 'DELETE LOW_PRIORITY FROM Monitors WHERE Id = ?'; @@ -531,7 +536,7 @@ MAIN: while( $loop ) { next; } if ( ! $Event->StartTime() ) { - Info("Event $$Event{Id} has no start time. deleting it."); + Info("Event $$Event{Id} has no start time."); if ( confirm() ) { $Event->delete(); $cleaned = 1; @@ -577,10 +582,11 @@ MAIN: while( $loop ) { $Event->StorageId($$fs_events{$db_event}->StorageId()); } if ( $$fs_events{$db_event}->StartTime() ne $Event->StartTime() ) { + Info("Updating StartTime on event $$Event{Id} from $$Event{StartTime} to $$fs_events{$db_event}{StartTime}"); if ( $$Event{Scheme} eq 'Deep' ) { - Info("Updating StartTime on event $$Event{Id} from $$Event{StartTime} to $$fs_events{$db_event}{StartTime}"); $Event->StartTime($$fs_events{$db_event}->StartTime()); } else { + $Event->StartTime($$fs_events{$db_event}->StartTime()); } $Event->save(); } @@ -994,6 +1000,25 @@ sub delete_empty_directories { } } # end sub delete_empty_directories +sub time_of_youngest_file { + my $dir = shift; + + if ( ! opendir(DIR, $dir) ) { + Error("Can't open directory '$dir': $!"); + return; + } + my $youngest = (stat($dir))[9]; + Debug("stat of $dir is $youngest"); + foreach my $file ( readdir( DIR ) ) { + next if $file =~ /^\./; + $_ = (stat($dir))[9]; + $youngest = $_ if $_ and ( $_ < $youngest ); + #Debug("stat of $dir is $_ < $youngest"); + } + Debug("stat of $dir is $youngest"); + return $youngest; +} # end sub time_of_youngest_file + 1; __END__ From 5120c6f540a06c7c57ee77bad775c92ced7b466e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Nov 2018 18:13:55 -0500 Subject: [PATCH 093/240] remove compile warning by assigning AV_CODEC_NONE to the codec_id. --- src/zm_rtsp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index 897859435..703328e2e 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -388,7 +388,7 @@ int RtspThread::run() { std::string trackUrl = mUrl; std::string controlUrl; - _AVCODECID codecId; + _AVCODECID codecId = AV_CODEC_ID_NONE; if ( mFormatContext->nb_streams >= 1 ) { for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) { From 490fb40917eef7b9fc47935bc1e17f09fcc6ee36 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 14 Nov 2018 09:22:38 -0500 Subject: [PATCH 094/240] DefaultView in the past was used to control whether the watch view starts up with ptz controls visible or the events list. Isaac changed the watch view to always have the controls visible... so this setting is no longer useful. --- db/zm_create.sql.in | 1 - db/zm_update-1.32.3.sql | 2 ++ web/skins/classic/views/monitor.php | 13 ------------- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 91c34163d..d19afd600 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -496,7 +496,6 @@ CREATE TABLE `Monitors` ( `TrackDelay` smallint(5) unsigned, `ReturnLocation` tinyint(3) NOT NULL default '-1', `ReturnDelay` smallint(5) unsigned, - `DefaultView` enum('Events','Control') NOT NULL default 'Events', `DefaultRate` smallint(5) unsigned NOT NULL default '100', `DefaultScale` smallint(5) unsigned NOT NULL default '100', `SignalCheckPoints` INT UNSIGNED NOT NULL default '0', diff --git a/db/zm_update-1.32.3.sql b/db/zm_update-1.32.3.sql index fe38baede..8f898de6b 100644 --- a/db/zm_update-1.32.3.sql +++ b/db/zm_update-1.32.3.sql @@ -7,3 +7,5 @@ -- INSERT INTO MonitorPresets VALUES (NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); + +ALTER TABLE Monitors DROP COLUMN DefaultView; diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index c030a151f..c2e6f357a 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -113,7 +113,6 @@ if ( ! $monitor ) { 'FPSReportInterval' => 100, 'RefBlendPerc' => 6, 'AlarmRefBlendPerc' => 6, - 'DefaultView' => 'Events', 'DefaultRate' => '100', 'DefaultScale' => '100', 'SignalCheckPoints' => '10', @@ -657,7 +656,6 @@ if ( $tab != 'misc' ) { - @@ -1010,17 +1008,6 @@ if ( $monitor->Type() == 'Local' ) { - DefaultRate() ); ?> DefaultScale() ); ?> From 3be31020b79fb3b84d8230f2781bef312cb89563 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 14 Nov 2018 15:54:01 -0500 Subject: [PATCH 095/240] Automatically add width to frames view when thumbnails are turned on. --- web/skins/classic/js/base.js | 2 +- web/skins/classic/views/js/event.js | 2 +- web/skins/classic/views/js/event.js.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/js/base.js b/web/skins/classic/js/base.js index 9eb93ee77..fa59c8103 100644 --- a/web/skins/classic/js/base.js +++ b/web/skins/classic/js/base.js @@ -40,7 +40,7 @@ var popupSizes = { 'export': { 'width': 400, 'height': 340 }, 'filter': { 'width': 900, 'height': 700 }, 'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 200 }, - 'frames': { 'width': 600, 'height': 600 }, + 'frames': { 'addWidth': 600, 'addHeight': 600 }, 'function': { 'width': 350, 'height': 260 }, 'group': { 'width': 760, 'height': 600 }, 'groups': { 'width': 540, 'height': 420 }, diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index e90016c1c..7f46936a9 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -887,7 +887,7 @@ function unarchiveEvent() { } function showEventFrames() { - createPopup( '?view=frames&eid='+eventData.Id, 'zmFrames', 'frames' ); + createPopup( '?view=frames&eid='+eventData.Id, 'zmFrames', 'frames', WEB_LIST_THUMB_WIDTH, WEB_LIST_THUMB_HEIGHT ); } function showStream() { diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php index dbdc5c514..b1924a752 100644 --- a/web/skins/classic/views/js/event.js.php +++ b/web/skins/classic/views/js/event.js.php @@ -55,3 +55,5 @@ var streamMode = ''; // var deleteString = ""; var causeString = ""; +var WEB_LIST_THUMB_WIDTH = ''; +var WEB_LIST_THUMB_HEIGHT = ''; From 3a409b26aa897d5154ca6f211a1089ff0c6e88bb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 14 Nov 2018 15:54:34 -0500 Subject: [PATCH 096/240] Use buttons instead of anchor tags for Prev/Next/FIrst/Last buttons --- web/skins/classic/views/frame.php | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/web/skins/classic/views/frame.php b/web/skins/classic/views/frame.php index 2e6bfb7b8..931951056 100644 --- a/web/skins/classic/views/frame.php +++ b/web/skins/classic/views/frame.php @@ -18,7 +18,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'Events' ) ) { +if ( !canView('Events') ) { $view = 'error'; return; } @@ -29,7 +29,7 @@ $eid = validInt($_REQUEST['eid']); if ( !empty($_REQUEST['fid']) ) $fid = validInt($_REQUEST['fid']); -$Event = new Event( $eid ); +$Event = new Event($eid); $Monitor = $Event->Monitor(); if ( !empty($fid) ) { @@ -39,7 +39,7 @@ if ( !empty($fid) ) { } else { $frame = dbFetchOne( 'SELECT * FROM Frames WHERE EventId = ? AND Score = ?', NULL, array( $eid, $Event->MaxScore() ) ); } -$Frame = new Frame( $frame ); +$Frame = new Frame($frame); $maxFid = $Event->Frames(); @@ -91,10 +91,10 @@ xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id()." - ".$Frame->Frame
-
-

Id()."-".$Frame->FrameId()." (".$Frame->Score().")" ?>

- - +
+

Id().'-'.$Frame->FrameId().' ('.$Frame->Score().')' ?>

+ +
@@ -109,11 +109,13 @@ xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id()." - ".$Frame->Frame

FrameId() > 1 ) { ?> - - -FrameId() < $maxFid ) { ?> - - + + +FrameId() < $maxFid ) { ?> + +

From aa8ac9c31c65ae857024fb7a46a7ce9e60de025c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 14 Nov 2018 15:54:45 -0500 Subject: [PATCH 097/240] spaces and quotes --- web/skins/classic/views/frames.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/frames.php b/web/skins/classic/views/frames.php index c50da5e7e..f27f004c3 100644 --- a/web/skins/classic/views/frames.php +++ b/web/skins/classic/views/frames.php @@ -18,11 +18,11 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'Events' ) ) { +if ( !canView('Events') ) { $view = 'error'; return; } -require_once( 'includes/Frame.php' ); +require_once('includes/Frame.php'); $Event = new Event( $_REQUEST['eid'] ); $sql = 'SELECT *, unix_timestamp( TimeStamp ) AS UnixTimeStamp FROM Frames WHERE EventID = ? ORDER BY FrameId'; @@ -30,7 +30,7 @@ $frames = dbFetchAll( $sql, NULL, array( $_REQUEST['eid'] ) ); $focusWindow = true; -xhtmlHeaders(__FILE__, translate('Frames')." - ".$Event->Id() ); +xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id() ); ?>
From 70d9fda7589b4d437d9bc305f5890b72895adde1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 14 Nov 2018 17:02:52 -0500 Subject: [PATCH 098/240] Implement a logging callback for avcodec to use our logging functions --- src/zm_ffmpeg.cpp | 39 ++++++++++++++++++++++++++++++++++++--- src/zm_logger.cpp | 1 + 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 79a1d8b26..00aee7961 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -24,14 +24,47 @@ #if HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE +void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs ) { + Logger *log = Logger::fetch(); + int log_level = 0; + if ( level == AV_LOG_QUIET ) { // -8 + log_level = Logger::NOLOG; + } else if ( level == AV_LOG_PANIC ) { //0 + log_level = Logger::PANIC; + } else if ( level == AV_LOG_FATAL ) { // 8 + log_level = Logger::FATAL; + } else if ( level == AV_LOG_ERROR ) { // 16 + log_level = Logger::ERROR; + } else if ( level == AV_LOG_WARNING ) { //24 + log_level = Logger::WARNING; + } else if ( level == AV_LOG_INFO ) { //32 + log_level = Logger::INFO; + } else if ( level == AV_LOG_VERBOSE ) { //40 + log_level = Logger::DEBUG1; + } else if ( level == AV_LOG_DEBUG ) { //48 + log_level = Logger::DEBUG2; + } else if ( level == AV_LOG_TRACE ) { + log_level = Logger::DEBUG8; + } else if ( level == AV_LOG_MAX_OFFSET ) { + log_level = Logger::DEBUG9; + } else { + Error("Unknown log level %d", level); + } + + if ( log ) { + log->logPrint(false, __FILE__, __LINE__, log_level, fmt, vargs); + } +} + void FFMPEGInit() { static bool bInit = false; if ( !bInit ) { - //if ( logDebugging() ) - //av_log_set_level( AV_LOG_DEBUG ); - //else + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else av_log_set_level( AV_LOG_QUIET ); + av_log_set_callback(log_libav_callback); av_register_all(); avformat_network_init(); bInit = true; diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 736d36377..9740a100f 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -581,6 +581,7 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co } } + void logInit(const char *name, const Logger::Options &options) { if ( !Logger::smInstance ) Logger::smInstance = new Logger(); From f2fc2348801a5c79b1858d9d027cf99e05f7317b Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 15 Nov 2018 08:26:54 -0600 Subject: [PATCH 099/240] rpm pkg - install zm php-fpm config in all cases for future nginx support --- distros/redhat/CMakeLists.txt | 6 ++---- distros/redhat/zoneminder.spec | 7 ++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index d940942c1..0b4938661 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -15,11 +15,11 @@ endif((NOT ZM_TARGET_DISTRO MATCHES "^fc") AND (ZM_WEB_USER STREQUAL "nginx")) # Configure the zoneminder service files configure_file(systemd/zoneminder.logrotate.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.logrotate @ONLY) +configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) if(ZM_WEB_USER STREQUAL "nginx") configure_file(nginx/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) configure_file(nginx/zoneminder.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.conf @ONLY) configure_file(nginx/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY) - configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) configure_file(nginx/README.Fedora ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) else(ZM_WEB_USER STREQUAL "nginx") configure_file(systemd/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) @@ -55,10 +55,8 @@ install(FILES misc/redalert.wav DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INST # Install zoneminder service files install(FILES zoneminder.logrotate DESTINATION /etc/logrotate.d RENAME zoneminder PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.php-fpm.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -if(ZM_WEB_USER STREQUAL "nginx") - install(FILES zoneminder.php-fpm.conf DESTINATION /etc/php-fpm.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ RENAME zoneminder.conf) -endif(ZM_WEB_USER STREQUAL "nginx") install(FILES zoneminder.service DESTINATION /usr/lib/systemd/system PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.tmpfiles DESTINATION /usr/lib/tmpfiles.d RENAME zoneminder.conf PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index ecba0fb5a..f594635ae 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -264,13 +264,10 @@ EOF %config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/*.conf %ghost %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/zmcustom.conf -%config(noreplace) %attr(644,root,root) /etc/zm/www/zoneminder.conf +%config(noreplace) %attr(644,root,root) %{_sysconfdir}/zm/www/zoneminder.conf +%config(noreplace) %{_sysconfdir}/www/zoneminder.php-fpm.conf %config(noreplace) %{_sysconfdir}/logrotate.d/zoneminder -%if 0%{?with_nginx} -%config(noreplace) %{_sysconfdir}/php-fpm.d/zoneminder.conf -%endif - %{_tmpfilesdir}/zoneminder.conf %{_unitdir}/zoneminder.service %{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy From 2f8c0654d5aab9bd2200cd63f29b1ce319d52564 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 15 Nov 2018 08:31:04 -0600 Subject: [PATCH 100/240] rpm pkg - fix for zm php-fpm config path --- distros/redhat/zoneminder.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index f594635ae..27cc59ba9 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -265,7 +265,7 @@ EOF %ghost %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/zmcustom.conf %config(noreplace) %attr(644,root,root) %{_sysconfdir}/zm/www/zoneminder.conf -%config(noreplace) %{_sysconfdir}/www/zoneminder.php-fpm.conf +%config(noreplace) %{_sysconfdir}/zm/www/zoneminder.php-fpm.conf %config(noreplace) %{_sysconfdir}/logrotate.d/zoneminder %{_tmpfilesdir}/zoneminder.conf From 9b46c92ac559348e31e4c965a4cb10272efb2e7f Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 15 Nov 2018 09:19:26 -0600 Subject: [PATCH 101/240] rpm pkg - add note to zm php-fpm config file --- distros/redhat/nginx/zoneminder.php-fpm.conf.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/distros/redhat/nginx/zoneminder.php-fpm.conf.in b/distros/redhat/nginx/zoneminder.php-fpm.conf.in index ffc44bbe0..a4537b236 100644 --- a/distros/redhat/nginx/zoneminder.php-fpm.conf.in +++ b/distros/redhat/nginx/zoneminder.php-fpm.conf.in @@ -1,3 +1,5 @@ +; This config file is needed when using ZoneMinder with web servers other +; than Apache. You can ignore this file if you are using Apache web server. ; Change the user and group of the default pool to the web server account [www] From f72651da5a3ab9f20fb1a21c8c8356815f322f4e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 15 Nov 2018 12:22:35 -0500 Subject: [PATCH 102/240] Add auth hash to ajax fps and status calls in zone edit --- web/skins/classic/views/js/zone.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/skins/classic/views/js/zone.js b/web/skins/classic/views/js/zone.js index 6389e3ce9..bfcd91943 100644 --- a/web/skins/classic/views/js/zone.js +++ b/web/skins/classic/views/js/zone.js @@ -471,6 +471,8 @@ function setAlarmState( currentAlarmState ) { } var streamCmdParms = "view=request&request=stream&connkey="+connKey; +if ( auth_hash ) + streamCmdParms += '&auth='+auth_hash; var streamCmdReq = new Request.JSON( { url: monitorUrl, method: 'get', @@ -552,6 +554,8 @@ function streamCmdQuery() { } var statusCmdParms = "view=request&request=status&entity=monitor&id="+monitorId+"&element[]=Status&element[]=FrameRate"; +if ( auth_hash ) + statusCmdParms += '&auth='+auth_hash; var statusCmdReq = new Request.JSON( { url: monitorUrl, method: 'get', From 415d43fafbde7151ac62053882414bd178318806 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 15 Nov 2018 12:23:52 -0500 Subject: [PATCH 103/240] Include Server Name when testing for CORS. Also be case insensitive. --- web/includes/functions.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 7fe174470..53ea7e199 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -47,7 +47,11 @@ function CORSHeaders() { return; } foreach( $Servers as $Server ) { - if ( preg_match('/^(https?:\/\/)?'.preg_quote($Server->Hostname(),'/').'/', $_SERVER['HTTP_ORIGIN']) ) { + if ( + preg_match('/^(https?:\/\/)?'.preg_quote($Server->Hostname(),'/').'/i', $_SERVER['HTTP_ORIGIN']) + or + preg_match('/^(https?:\/\/)?'.preg_quote($Server->Name(),'/').'/i', $_SERVER['HTTP_ORIGIN']) + ) { $valid = true; Logger::Debug("Setting Access-Controll-Allow-Origin from " . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); From 5c2e5d89ed5fbf394cac971e6ff86cb3070e5011 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 15 Nov 2018 19:53:45 -0600 Subject: [PATCH 104/240] fix gpl mailing address This makes rpmlint & lintian complain less --- web/skins/classic/views/storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/storage.php b/web/skins/classic/views/storage.php index dafd7bb67..3aecdb042 100644 --- a/web/skins/classic/views/storage.php +++ b/web/skins/classic/views/storage.php @@ -15,7 +15,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // if ( !canEdit( 'System' ) ) { From e5f2212a32bd9ccb32c793f12a8c3e7aae5d3925 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 15 Nov 2018 20:00:53 -0600 Subject: [PATCH 105/240] fix gpl mailing address --- scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm | 2 +- scripts/ZoneMinder/lib/ZoneMinder/Control/Reolink.pm | 2 +- scripts/ZoneMinder/lib/ZoneMinder/Storage.pm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm index 8465ee472..ec3bbfc70 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/IPCAMIOS.pm @@ -16,7 +16,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ========================================================================== # diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Reolink.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Reolink.pm index 370d463c3..7a2f72fc6 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Reolink.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Reolink.pm @@ -16,7 +16,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ========================================================================== # diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Storage.pm b/scripts/ZoneMinder/lib/ZoneMinder/Storage.pm index 134752594..1f7c1b9fe 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Storage.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Storage.pm @@ -15,7 +15,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # ========================================================================== # From 8df9e4c1ee23ebe2142bcaed101c567007539d60 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 15 Nov 2018 20:18:56 -0600 Subject: [PATCH 106/240] Update zoneminder.logrotate.in --- distros/redhat/systemd/zoneminder.logrotate.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/distros/redhat/systemd/zoneminder.logrotate.in b/distros/redhat/systemd/zoneminder.logrotate.in index b4919eb5e..210a84c07 100644 --- a/distros/redhat/systemd/zoneminder.logrotate.in +++ b/distros/redhat/systemd/zoneminder.logrotate.in @@ -2,7 +2,11 @@ missingok notifempty sharedscripts + delaycompress + compress postrotate - @BINDIR@/zmpkg.pl logrot 2> /dev/null > /dev/null || : + @BINDIR@/zmpkg.pl logrot > /dev/null 2>/dev/null || true endscript + daily + rotate 7 } From b353b625eb48751d0e1b6f72fe1f5440d8c7cccc Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 16 Nov 2018 10:40:39 -0600 Subject: [PATCH 107/240] rpm - configure the nginx config file in all cases --- distros/redhat/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index 0b4938661..37643cd89 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -16,9 +16,9 @@ endif((NOT ZM_TARGET_DISTRO MATCHES "^fc") AND (ZM_WEB_USER STREQUAL "nginx")) # Configure the zoneminder service files configure_file(systemd/zoneminder.logrotate.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.logrotate @ONLY) configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) +configure_file(nginx/zoneminder.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.conf @ONLY) if(ZM_WEB_USER STREQUAL "nginx") configure_file(nginx/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) - configure_file(nginx/zoneminder.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.conf @ONLY) configure_file(nginx/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY) configure_file(nginx/README.Fedora ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) else(ZM_WEB_USER STREQUAL "nginx") @@ -56,7 +56,7 @@ install(FILES misc/redalert.wav DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INST install(FILES zoneminder.logrotate DESTINATION /etc/logrotate.d RENAME zoneminder PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.php-fpm.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) - +install(FILES zoneminder.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.service DESTINATION /usr/lib/systemd/system PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.tmpfiles DESTINATION /usr/lib/tmpfiles.d RENAME zoneminder.conf PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) From 713e810632b09c25ccd6838f0a832da48518a471 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 16 Nov 2018 17:08:23 -0600 Subject: [PATCH 108/240] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 40 +++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 4e33ce4e0..512b5df1f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,23 +1,43 @@ -You should only file an issue if you found a bug. Feature and enhancement requests, general discussions and support questions should occur in one of the following areas: +**THIS FORUM IS FOR BUG REPORTS ONLY** + +Do not post feature or enhancement requests, general discussions or support questions here. + +Feature and enhancement requests, general discussions and support questions should occur in one of the following areas: - The [ZoneMinder-Chat Slack channel](https://zoneminder-chat.herokuapp.com/) - The [ZoneMinder Forum](https://forums.zoneminder.com/) -**Do not post feature or enhancement requests, general discussions or support questions here.** - Docker related issues should be posted here: https://github.com/ZoneMinder/zmdockerfiles -Make sure you are running the latest version of ZoneMinder before reporting an issue. +In order to submit a bug report, please populate the field below. This is required. -**ZoneMinder Version (`zmaudit.pl -v`):** +**Describe Your Environment** +- Version of ZoneMinder [release version, development version, or commit] +- How you installed ZoneMinder [e.g. PPA, RPMFusion, from-source, etc] +- Full name and version of OS -**Are you using a development snapshot / git checkout? If so, what is the latest commit? (`git rev-parse HEAD`):** +**If the issue concerns a camera** +- Make and Model +- frame rate +- resolution +- ZoneMinder Source Type: -**Linux Distribution and Version (`cat /etc/os-release` or `cat /etc/redhat-release`):** +**Describe the bug** +A clear and concise description of what the bug is. -**If the issue concerns a camera, provide the make, model, frame rate, resolution and ZoneMinder Source Type:** +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error -**Relevant log lines:** +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Debug Logs** ``` -log lines here + + + ``` From 6883d5b532e08f88993b5c951784929a189a18f5 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 16 Nov 2018 17:11:05 -0600 Subject: [PATCH 109/240] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 512b5df1f..f52716c2d 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -2,14 +2,14 @@ Do not post feature or enhancement requests, general discussions or support questions here. -Feature and enhancement requests, general discussions and support questions should occur in one of the following areas: +Feature and enhancement requests, general discussions, and support questions should occur in one of the following areas: - The [ZoneMinder-Chat Slack channel](https://zoneminder-chat.herokuapp.com/) - The [ZoneMinder Forum](https://forums.zoneminder.com/) Docker related issues should be posted here: https://github.com/ZoneMinder/zmdockerfiles -In order to submit a bug report, please populate the field below. This is required. +In order to submit a bug report, please populate the fields below. This is required. **Describe Your Environment** - Version of ZoneMinder [release version, development version, or commit] From 15e720d4f7782c8f2355736509c6b3fee080e716 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 16 Nov 2018 17:50:54 -0600 Subject: [PATCH 110/240] Create config.yml --- .github/config.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/config.yml diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 000000000..543a2c160 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,21 @@ +# Configuration for welcome - https://github.com/behaviorbot/welcome + +# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome + +# Comment to be posted to on first time issues +newIssueWelcomeComment: > + Thanks for opening your first issue here! Just a reminder, this forum is for Bug Reports only. Be sure to follow the issue template! + +# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome + +# Comment to be posted to on PRs from first time contributors in your repository +#newPRWelcomeComment: > +# Thanks for opening this pull request! Please check out our contributing guidelines. + +# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge + +# Comment to be posted to on pull requests merged by a first time user +#firstPRMergeComment: > +# Congrats on merging your first pull request! We here at behaviorbot are proud of you! + +# It is recommend to include as many gifs and emojis as possible From 21d311942fdf32b9a879e488a445cc472a8480c3 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 16 Nov 2018 17:54:24 -0600 Subject: [PATCH 111/240] Create no-response.yml --- .github/no-response.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/no-response.yml diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 000000000..7e40c036f --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,13 @@ +# Configuration for probot-no-response - https://github.com/probot/no-response + +# Number of days of inactivity before an Issue is closed for lack of response +daysUntilClose: 7 +# Label requiring a response +responseRequiredLabel: more-information-needed +# Comment to post when closing an Issue for lack of response. Set to `false` to disable +closeComment: > + This issue has been automatically closed because there has been no response + to our request for more information from the original author. With only the + information that is currently in the issue, we don't have enough information + to take action. Please reach out if you have or find the answers we need so + that we can investigate further. From b4f77077e9aeffec8b92f163eb29f3e325462989 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 16 Nov 2018 18:33:54 -0600 Subject: [PATCH 112/240] Update zmdc.pl.in temporary fix to #2292 --- scripts/zmdc.pl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in index ac83fa6d6..4b32b3a65 100644 --- a/scripts/zmdc.pl.in +++ b/scripts/zmdc.pl.in @@ -438,7 +438,7 @@ sub start { $dbh = zmDbConnect(1); # This logReinit is required. Not sure why. - #logReinit(); + logReinit(); $process->{pid} = $cpid; $process->{started} = time(); From 87140ecdb59d60c2f845e082bf94fae5094da28f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 17 Nov 2018 10:39:42 -0500 Subject: [PATCH 113/240] white space and quiet warning --- src/zm_event.cpp | 2 +- web/skins/classic/views/zone.php | 64 ++++++++++++++++---------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 8d3108b31..fbf5cf848 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -174,7 +174,7 @@ Event::Event( Error("Can't mkdir %s: %s", path, strerror(errno)); } } else { - path_ptr += snprintf(path, sizeof(path), "/%" PRIu64, id); + snprintf(path, sizeof(path), "/%" PRIu64, id); if ( mkdir(path, 0755) ) { if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); diff --git a/web/skins/classic/views/zone.php b/web/skins/classic/views/zone.php index f6a763c19..6c04abf2f 100644 --- a/web/skins/classic/views/zone.php +++ b/web/skins/classic/views/zone.php @@ -62,39 +62,39 @@ $minY = 0; $maxY = $monitor->Height()-1; if ( !isset($newZone) ) { - if ( $zid > 0 ) { - $zone = dbFetchOne( 'SELECT * FROM Zones WHERE MonitorId = ? AND Id=?', NULL, array( $monitor->Id(), $zid ) ); - } else { - $zone = array( - 'Id' => 0, - 'Name' => translate('New'), - 'Type' => 'Active', - 'MonitorId' => $monitor->Id(), - 'NumCoords' => 4, - 'Coords' => sprintf( "%d,%d %d,%d, %d,%d %d,%d", $minX, $minY, $maxX, $minY, $maxX, $maxY, $minX, $maxY ), - 'Area' => $monitor->Width() * $monitor->Height(), - 'AlarmRGB' => 0xff0000, - 'CheckMethod' => 'Blobs', - 'MinPixelThreshold' => '', - 'MaxPixelThreshold' => '', - 'MinAlarmPixels' => '', - 'MaxAlarmPixels' => '', - 'FilterX' => '', - 'FilterY' => '', - 'MinFilterPixels' => '', - 'MaxFilterPixels' => '', - 'MinBlobPixels' => '', - 'MaxBlobPixels' => '', - 'MinBlobs' => '', - 'MaxBlobs' => '', - 'OverloadFrames' => '', - 'ExtendAlarmFrames' => '', - ); - } - $zone['Points'] = coordsToPoints( $zone['Coords'] ); - $zone['AreaCoords'] = preg_replace( '/\s+/', ',', $zone['Coords'] ); + if ( $zid > 0 ) { + $zone = dbFetchOne( 'SELECT * FROM Zones WHERE MonitorId = ? AND Id=?', NULL, array( $monitor->Id(), $zid ) ); + } else { + $zone = array( + 'Id' => 0, + 'Name' => translate('New'), + 'Type' => 'Active', + 'MonitorId' => $monitor->Id(), + 'NumCoords' => 4, + 'Coords' => sprintf( "%d,%d %d,%d, %d,%d %d,%d", $minX, $minY, $maxX, $minY, $maxX, $maxY, $minX, $maxY ), + 'Area' => $monitor->Width() * $monitor->Height(), + 'AlarmRGB' => 0xff0000, + 'CheckMethod' => 'Blobs', + 'MinPixelThreshold' => '', + 'MaxPixelThreshold' => '', + 'MinAlarmPixels' => '', + 'MaxAlarmPixels' => '', + 'FilterX' => '', + 'FilterY' => '', + 'MinFilterPixels' => '', + 'MaxFilterPixels' => '', + 'MinBlobPixels' => '', + 'MaxBlobPixels' => '', + 'MinBlobs' => '', + 'MaxBlobs' => '', + 'OverloadFrames' => '', + 'ExtendAlarmFrames' => '', + ); + } + $zone['Points'] = coordsToPoints( $zone['Coords'] ); + $zone['AreaCoords'] = preg_replace( '/\s+/', ',', $zone['Coords'] ); - $newZone = $zone; + $newZone = $zone; } # end if new Zone # Ensure Zone fits within the limits of the Monitor From ac0e8c9b0b0b5bb5005fbbdc755aa937ad948c64 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 10:45:08 -0600 Subject: [PATCH 114/240] initial support for subpackages --- distros/redhat/CMakeLists.txt | 85 ++++---- .../com.zoneminder.systemctl.rules.apache.in | 7 + distros/redhat/apache/zm-apache.conf.in | 8 + ...nder.conf.in => zoneminder.apache.conf.in} | 0 .../zoneminder.apache.tmpfiles.in} | 0 distros/redhat/{misc => common}/redalert.wav | Bin .../zoneminder.logrotate.in | 0 .../{systemd => common}/zoneminder.service.in | 5 +- distros/redhat/misc/local_zoneminder.te | 125 ------------ .../com.zoneminder.systemctl.rules.nginx | 7 + distros/redhat/nginx/zm-nginx.conf | 9 + distros/redhat/nginx/zm-web-user.conf | 3 + ...inder.conf.in => zoneminder.nginx.conf.in} | 0 .../redhat/nginx/zoneminder.nginx.tmpfiles.in | 8 + distros/redhat/nginx/zoneminder.service.in | 22 -- distros/redhat/nginx/zoneminder.tmpfiles.in | 8 - distros/redhat/readme/README | 29 +++ .../README.Fedora => readme/README.nginx} | 0 distros/redhat/zoneminder.spec | 189 +++++++++++++----- 19 files changed, 261 insertions(+), 244 deletions(-) create mode 100644 distros/redhat/apache/com.zoneminder.systemctl.rules.apache.in create mode 100644 distros/redhat/apache/zm-apache.conf.in rename distros/redhat/apache/{zoneminder.conf.in => zoneminder.apache.conf.in} (100%) rename distros/redhat/{systemd/zoneminder.tmpfiles.in => apache/zoneminder.apache.tmpfiles.in} (100%) rename distros/redhat/{misc => common}/redalert.wav (100%) rename distros/redhat/{systemd => common}/zoneminder.logrotate.in (100%) rename distros/redhat/{systemd => common}/zoneminder.service.in (79%) delete mode 100644 distros/redhat/misc/local_zoneminder.te create mode 100644 distros/redhat/nginx/com.zoneminder.systemctl.rules.nginx create mode 100644 distros/redhat/nginx/zm-nginx.conf create mode 100644 distros/redhat/nginx/zm-web-user.conf rename distros/redhat/nginx/{zoneminder.conf.in => zoneminder.nginx.conf.in} (100%) create mode 100644 distros/redhat/nginx/zoneminder.nginx.tmpfiles.in delete mode 100644 distros/redhat/nginx/zoneminder.service.in delete mode 100644 distros/redhat/nginx/zoneminder.tmpfiles.in create mode 100644 distros/redhat/readme/README rename distros/redhat/{nginx/README.Fedora => readme/README.nginx} (100%) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index 37643cd89..bf4e2b40d 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -1,5 +1,10 @@ # CMakeLists.txt for the Redhat Target Distros. +# +# General strategy is to configure and install all files specific to Apache and Nginx +# Then let the rpm specfile sort them into the appropriate sub-package +# + # Display a message to show the RHEL build options are being processed. if(ZM_TARGET_DISTRO MATCHES "^el") message([STATUS] "Starting RHEL Build Options" ...) @@ -9,33 +14,38 @@ else(ZM_TARGET_DISTRO MATCHES "^el") message([WARNING] "Unknown Build Option Detected" ...) endif(ZM_TARGET_DISTRO MATCHES "^el") -if((NOT ZM_TARGET_DISTRO MATCHES "^fc") AND (ZM_WEB_USER STREQUAL "nginx")) - message([FATAL_ERROR] "Experimental Nginx support is currently only supported on Fedora" ...) -endif((NOT ZM_TARGET_DISTRO MATCHES "^fc") AND (ZM_WEB_USER STREQUAL "nginx")) +# +# CONFIGURE STAGE +# -# Configure the zoneminder service files -configure_file(systemd/zoneminder.logrotate.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.logrotate @ONLY) -configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) -configure_file(nginx/zoneminder.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.conf @ONLY) -if(ZM_WEB_USER STREQUAL "nginx") - configure_file(nginx/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) - configure_file(nginx/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY) - configure_file(nginx/README.Fedora ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) -else(ZM_WEB_USER STREQUAL "nginx") - configure_file(systemd/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) - configure_file(apache/zoneminder.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.conf @ONLY) - configure_file(systemd/zoneminder.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.tmpfiles @ONLY) - if( ZM_TARGET_DISTRO MATCHES "^fc") - configure_file(readme/README.Fedora ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) - else( ZM_TARGET_DISTRO MATCHES "^fc") - configure_file(readme/README.Redhat7 ${CMAKE_CURRENT_SOURCE_DIR}/readme/README COPYONLY) - endif( ZM_TARGET_DISTRO MATCHES "^fc") -endif(ZM_WEB_USER STREQUAL "nginx") - -# Create several empty folders +# Configure the common zoneminder files +configure_file(common/zoneminder.logrotate.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.logrotate @ONLY) +configure_file(common/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp) -# Install the empty folders +# Configure the Apache zoneminder files +configure_file(apache/zm-apache.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zm-apache.conf @ONLY) +configure_file(apache/zoneminder.apache.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.apache.conf @ONLY) +configure_file(apache/zoneminder.apache.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.apache.tmpfiles.conf @ONLY) +configure_file(apache/com.zoneminder.systemctl.rules.apache.in ${CMAKE_CURRENT_SOURCE_DIR}/com.zoneminder.systemctl.rules.apache @ONLY) + +# Configure the Nginx zoneminder files +configure_file(nginx/zm-nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-nginx.conf COPYONLY) +configure_file(nginx/zoneminder.nginx.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.conf @ONLY) +configure_file(nginx/zoneminder.nginx.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.tmpfiles.conf @ONLY) +configure_file(nginx/zm-web-user.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-web-user.conf COPYONLY) +configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) +configure_file(nginx/com.zoneminder.systemctl.rules.nginx.in ${CMAKE_CURRENT_SOURCE_DIR}/com.zoneminder.systemctl.rules.nginx COPYONLY) + +# +# INSTALLATION STAGE +# + + +# Install the common zoneminder files +install(FILES zoneminder.logrotate DESTINATION /etc/logrotate.d RENAME zoneminder PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.service DESTINATION /usr/lib/systemd/system PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) + install(DIRECTORY sock swap DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY zoneminder DESTINATION /var/log DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY zoneminder DESTINATION /var/run DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) @@ -43,6 +53,22 @@ install(DIRECTORY zoneminder DESTINATION /var/cache DIRECTORY_PERMISSIONS OWNER_ install(DIRECTORY zoneminder-upload DESTINATION /var/spool DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY events images temp DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +# Install the Apache zoneminder files +install(FILES zm-apache.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.apache.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.apache.tmpfiles.conf DESTINATION /usr/lib/tmpfiles.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES com.zoneminder.systemctl.rules.apache DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) + +# Install the Nginx zoneminder files +install(FILES zm-nginx.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.nginx.tmpfiles.conf DESTINATION /usr/lib/tmpfiles.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES com.zoneminder.systemctl.rules.nginx DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zm-web-user.conf DESTINATION /etc/zm/conf.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.php-fpm.conf DESTINATION /etc/php-fpm.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) + +# Miscellaneous + # Symlink the cake php temp folder to the ZoneMinder temp folder install(CODE "execute_process(COMMAND ln -sf ../../../../../../var/lib/zoneminder/temp \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/api/app/tmp\")") @@ -50,14 +76,5 @@ install(CODE "execute_process(COMMAND ln -sf ../../../../../../var/lib/zoneminde install(CODE "execute_process(COMMAND ln -sf ../../java/cambozola.jar \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/cambozola.jar\")") # Install auxiliary files -install(FILES misc/redalert.wav DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/sounds PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - -# Install zoneminder service files -install(FILES zoneminder.logrotate DESTINATION /etc/logrotate.d RENAME zoneminder PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -install(FILES zoneminder.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -install(FILES zoneminder.php-fpm.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -install(FILES zoneminder.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) - -install(FILES zoneminder.service DESTINATION /usr/lib/systemd/system PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -install(FILES zoneminder.tmpfiles DESTINATION /usr/lib/tmpfiles.d RENAME zoneminder.conf PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES common/redalert.wav DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/zoneminder/www/sounds PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/distros/redhat/apache/com.zoneminder.systemctl.rules.apache.in b/distros/redhat/apache/com.zoneminder.systemctl.rules.apache.in new file mode 100644 index 000000000..d101dad69 --- /dev/null +++ b/distros/redhat/apache/com.zoneminder.systemctl.rules.apache.in @@ -0,0 +1,7 @@ +polkit.addRule(function(action, subject) { + if (action.id == "com.zoneminder.policykit.pkexec.run-zmsystemctl" && + subject.user != "@WEB_USER@") { + return polkit.Result.NO; + } + +}); diff --git a/distros/redhat/apache/zm-apache.conf.in b/distros/redhat/apache/zm-apache.conf.in new file mode 100644 index 000000000..edf3a090d --- /dev/null +++ b/distros/redhat/apache/zm-apache.conf.in @@ -0,0 +1,8 @@ +# Additional config directions for ZoneMinder with Apache web server + +[Unit] +After=httpd.service + +[Service] +User=@WEB_USER@ +Group=@WEB_GROUP@ diff --git a/distros/redhat/apache/zoneminder.conf.in b/distros/redhat/apache/zoneminder.apache.conf.in similarity index 100% rename from distros/redhat/apache/zoneminder.conf.in rename to distros/redhat/apache/zoneminder.apache.conf.in diff --git a/distros/redhat/systemd/zoneminder.tmpfiles.in b/distros/redhat/apache/zoneminder.apache.tmpfiles.in similarity index 100% rename from distros/redhat/systemd/zoneminder.tmpfiles.in rename to distros/redhat/apache/zoneminder.apache.tmpfiles.in diff --git a/distros/redhat/misc/redalert.wav b/distros/redhat/common/redalert.wav similarity index 100% rename from distros/redhat/misc/redalert.wav rename to distros/redhat/common/redalert.wav diff --git a/distros/redhat/systemd/zoneminder.logrotate.in b/distros/redhat/common/zoneminder.logrotate.in similarity index 100% rename from distros/redhat/systemd/zoneminder.logrotate.in rename to distros/redhat/common/zoneminder.logrotate.in diff --git a/distros/redhat/systemd/zoneminder.service.in b/distros/redhat/common/zoneminder.service.in similarity index 79% rename from distros/redhat/systemd/zoneminder.service.in rename to distros/redhat/common/zoneminder.service.in index 68918ab9e..540c2f939 100644 --- a/distros/redhat/systemd/zoneminder.service.in +++ b/distros/redhat/common/zoneminder.service.in @@ -1,9 +1,10 @@ # ZoneMinder systemd unit file for RedHat distros and clones +# See drop-in folder for additional config directives [Unit] Description=ZoneMinder CCTV recording and security system -After=network.target mariadb.service httpd.service -Requires=mariadb.service httpd.service +After=network.target mariadb.service +Requires=mariadb.service [Service] User=@WEB_USER@ diff --git a/distros/redhat/misc/local_zoneminder.te b/distros/redhat/misc/local_zoneminder.te deleted file mode 100644 index c49505785..000000000 --- a/distros/redhat/misc/local_zoneminder.te +++ /dev/null @@ -1,125 +0,0 @@ -module local_zoneminder 1.2; - -require { - type afs_ka_port_t; - type netsupport_port_t; - type port_t; - type presence_port_t; - type postfix_master_t; - type postfix_qmgr_t; - type postfix_pickup_t; - type httpd_t; - type var_lib_t; - type ionixnetmon_port_t; - type glance_port_t; - type mmcc_port_t; - type postfix_master_t; - type commplex_port_t; - type syslogd_port_t; - type dcc_port_t; - type sip_port_t; - type amqp_port_t; - type condor_port_t; - type afs_fs_port_t; - type nodejs_debug_port_t; - type httpd_var_lib_t; - type websm_port_t; - type afs_pt_port_t; - type postfix_qmgr_t; - type git_port_t; - type ipp_port_t; - type aol_port_t; - type unconfined_t; - type kernel_t; - type init_t; - type auditd_t; - type mysqld_t; - type httpd_log_t; - type syslogd_t; - type httpd_t; - type initrc_state_t; - type initrc_t; - type var_lib_t; - type udev_t; - type mysqld_safe_t; - type sshd_t; - type crond_t; - type getty_t; - type httpd_var_lib_t; - type initrc_var_run_t; - type tmpfs_t; - type dhcpc_t; - type v4l_device_t; - type file_t; - class sock_file { write create unlink }; - class unix_stream_socket { read connectto }; - class lnk_file { write create getattr read lock unlink }; - class dir {search getattr }; - class udp_socket name_bind; - class file { write getattr read lock unlink open }; - class shm { unix_read unix_write associate read write getattr }; - class chr_file getattr; -} - -#============= httpd_t ============== -allow httpd_t auditd_t:dir { search getattr }; -allow httpd_t auditd_t:file { read getattr open }; -allow httpd_t crond_t:dir { search getattr }; -allow httpd_t crond_t:file { read getattr open }; -allow httpd_t dhcpc_t:dir { search getattr }; -allow httpd_t dhcpc_t:file { read getattr open }; -allow httpd_t getty_t:dir { search getattr }; -allow httpd_t getty_t:file { read getattr open }; -allow httpd_t httpd_log_t:file write; -allow httpd_t httpd_var_lib_t:lnk_file { write getattr read lock unlink }; -allow httpd_t init_t:dir { search getattr }; -allow httpd_t init_t:file { read getattr open }; -#!!!! The source type 'httpd_t' can write to a 'file' of the following types: -#squirrelmail_spool_t, mirrormanager_var_run_t, dirsrvadmin_config_t, httpd_lock_t, httpd_tmp_t, dirsrv_config_t, dirsrvadmin_tmp_t, httpd_cache_t, httpd_tmpfs_t, httpd_squirrelmail_t, dirsrv_var_run_t, dirsrv_var_log_t, httpd_var_lib_t, httpd_var_run_t, zarafa_var_lib_t, httpd_prewikka_rw_content_t, httpd_mediawiki_rw_content_t, httpd_squid_rw_content_t, passenger_var_run_t, httpd_smokeping_cgi_rw_content_t, httpd_openshift_rw_content_t, httpd_dirsrvadmin_rw_content_t, httpd_w3c_validator_rw_content_t, httpd_collectd_rw_content_t, cluster_var_lib_t, cluster_var_run_t, httpd_user_rw_content_t, httpd_awstats_rw_content_t, httpdcontent, root_t, httpd_cobbler_rw_content_t, httpd_munin_rw_content_t, cluster_conf_t, httpd_bugzilla_rw_content_t, passenger_tmp_t, httpd_cvs_rw_content_t, httpd_git_rw_content_t, httpd_sys_rw_content_t, httpd_sys_rw_content_t, httpd_nagios_rw_content_t, httpd_apcupsd_cgi_rw_content_t, httpd_nutups_cgi_rw_content_t, httpd_dspam_rw_content_t - -allow httpd_t initrc_state_t:file { read write getattr unlink open }; -allow httpd_t initrc_t:unix_stream_socket connectto; -allow httpd_t initrc_t:shm { unix_read unix_write associate read write getattr }; -allow httpd_t initrc_var_run_t:file { write read lock open }; -allow httpd_t kernel_t:dir { search getattr }; -allow httpd_t kernel_t:file { read getattr open }; -allow httpd_t mysqld_safe_t:dir { search getattr }; -allow httpd_t mysqld_safe_t:file { read getattr open }; -allow httpd_t mysqld_t:dir { search getattr }; -allow httpd_t mysqld_t:file { read getattr open }; -allow httpd_t sshd_t:dir { search getattr }; -allow httpd_t sshd_t:file { read getattr open }; -allow httpd_t syslogd_t:dir { search getattr }; -allow httpd_t syslogd_t:file { read getattr open }; -allow httpd_t tmpfs_t:sock_file write; -allow httpd_t udev_t:dir { search getattr }; -allow httpd_t udev_t:file { read getattr open }; -allow httpd_t unconfined_t:dir { search getattr }; -allow httpd_t unconfined_t:file { read getattr open }; -allow httpd_t var_lib_t:lnk_file { write getattr read lock unlink }; -allow httpd_t var_lib_t:sock_file { write unlink }; -allow httpd_t v4l_device_t:chr_file getattr; -allow httpd_t afs_fs_port_t:udp_socket name_bind; -allow httpd_t afs_ka_port_t:udp_socket name_bind; -allow httpd_t afs_pt_port_t:udp_socket name_bind; -allow httpd_t amqp_port_t:udp_socket name_bind; -allow httpd_t aol_port_t:udp_socket name_bind; -allow httpd_t commplex_port_t:udp_socket name_bind; -allow httpd_t condor_port_t:udp_socket name_bind; -allow httpd_t dcc_port_t:udp_socket name_bind; -allow httpd_t git_port_t:udp_socket name_bind; -allow httpd_t glance_port_t:udp_socket name_bind; -allow httpd_t httpd_var_lib_t:lnk_file create; -allow httpd_t ionixnetmon_port_t:udp_socket name_bind; -allow httpd_t ipp_port_t:udp_socket name_bind; -allow httpd_t mmcc_port_t:udp_socket name_bind; -allow httpd_t netsupport_port_t:udp_socket name_bind; -allow httpd_t nodejs_debug_port_t:udp_socket name_bind; -allow httpd_t port_t:udp_socket name_bind; -allow httpd_t postfix_master_t:dir { search getattr }; -allow httpd_t postfix_master_t:file { read getattr open }; -allow httpd_t postfix_pickup_t:dir { search getattr }; -allow httpd_t postfix_pickup_t:file { read getattr open }; -allow httpd_t postfix_qmgr_t:dir { search getattr }; -allow httpd_t postfix_qmgr_t:file { read getattr open }; -allow httpd_t presence_port_t:udp_socket name_bind; diff --git a/distros/redhat/nginx/com.zoneminder.systemctl.rules.nginx b/distros/redhat/nginx/com.zoneminder.systemctl.rules.nginx new file mode 100644 index 000000000..8eaa78d5c --- /dev/null +++ b/distros/redhat/nginx/com.zoneminder.systemctl.rules.nginx @@ -0,0 +1,7 @@ +polkit.addRule(function(action, subject) { + if (action.id == "com.zoneminder.policykit.pkexec.run-zmsystemctl" && + subject.user != "nginx") { + return polkit.Result.NO; + } + +}); diff --git a/distros/redhat/nginx/zm-nginx.conf b/distros/redhat/nginx/zm-nginx.conf new file mode 100644 index 000000000..98ca1943a --- /dev/null +++ b/distros/redhat/nginx/zm-nginx.conf @@ -0,0 +1,9 @@ +# Additional config directives for ZoneMinder with Nginx web server + +[Unit] +After=nginx.service php-fpm.service fcgiwrap.service +Requires=php-fpm.service fcgiwrap.service + +[Service] +User=nginx +Group=nginx diff --git a/distros/redhat/nginx/zm-web-user.conf b/distros/redhat/nginx/zm-web-user.conf new file mode 100644 index 000000000..3146679fd --- /dev/null +++ b/distros/redhat/nginx/zm-web-user.conf @@ -0,0 +1,3 @@ +ZM_WEB_USER=nginx +ZM_WEB_GROUP=nginx + diff --git a/distros/redhat/nginx/zoneminder.conf.in b/distros/redhat/nginx/zoneminder.nginx.conf.in similarity index 100% rename from distros/redhat/nginx/zoneminder.conf.in rename to distros/redhat/nginx/zoneminder.nginx.conf.in diff --git a/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in b/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in new file mode 100644 index 000000000..46dbd99fe --- /dev/null +++ b/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in @@ -0,0 +1,8 @@ +D @ZM_TMPDIR@ 0755 nginx nginx +D @ZM_SOCKDIR@ 0755 nginx nginx +D @ZM_CACHEDIR@ 0755 nginx nginx +d @ZM_DIR_EVENTS@ 0755 nginx nginx +D @ZM_DIR_IMAGES@ 0755 nginx nginx +D /var/lib/php/session 770 root nginx +D /var/lib/php/wsdlcache 770 root nginx + diff --git a/distros/redhat/nginx/zoneminder.service.in b/distros/redhat/nginx/zoneminder.service.in deleted file mode 100644 index 7e2e36585..000000000 --- a/distros/redhat/nginx/zoneminder.service.in +++ /dev/null @@ -1,22 +0,0 @@ -# ZoneMinder systemd unit file for Fedora -# Replace mariadb with community-mysql if using mysql service instead of mariadb - -[Unit] -Description=ZoneMinder CCTV recording and security system -After=network.target mariadb.service nginx.service php-fpm.service fcgiwrap.service -Requires=mariadb.service nginx.service php-fpm.service fcgiwrap.service - -[Service] -User=@WEB_USER@ -Group=@WEB_GROUP@ -Type=forking -ExecStart=@BINDIR@/zmpkg.pl start -ExecReload=@BINDIR@/zmpkg.pl restart -ExecStop=@BINDIR@/zmpkg.pl stop -PIDFile=@ZM_RUNDIR@/zm.pid -Environment=TZ=/etc/localtime -RuntimeDirectory=zoneminder -RuntimeDirectoryMode=0755 - -[Install] -WantedBy=multi-user.target diff --git a/distros/redhat/nginx/zoneminder.tmpfiles.in b/distros/redhat/nginx/zoneminder.tmpfiles.in deleted file mode 100644 index 07bae0900..000000000 --- a/distros/redhat/nginx/zoneminder.tmpfiles.in +++ /dev/null @@ -1,8 +0,0 @@ -D @ZM_TMPDIR@ 0755 @WEB_USER@ @WEB_GROUP@ -D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@ -D @ZM_CACHEDIR@ 0755 @WEB_USER@ @WEB_GROUP@ -d @ZM_DIR_EVENTS@ 0755 @WEB_USER@ @WEB_GROUP@ -D @ZM_DIR_IMAGES@ 0755 @WEB_USER@ @WEB_GROUP@ -D /var/lib/php/session 770 root @WEB_GROUP@ -D /var/lib/php/wsdlcache 770 root @WEB_GROUP@ - diff --git a/distros/redhat/readme/README b/distros/redhat/readme/README new file mode 100644 index 000000000..e25001863 --- /dev/null +++ b/distros/redhat/readme/README @@ -0,0 +1,29 @@ +What's New +========== + +1. See the ZoneMinder release notes for a list of new features: + https://github.com/ZoneMinder/zoneminder/releases + +2. The contents of the ZoneMinder Apache config file have changed. In + addition, this ZoneMinder package now requires you to manually symlink the + ZoneMinder Apache config file. See new install step 6 and upgrade step 3 + below for details. + +3. This package has been split into sub-packages to allow compatibility with + other web servers. Here is a breakdown of the available packages: + + zoneminder - Meta-package installs zoneminder-common and zoneminder-httpd + This exists soley for backwards compaitilibty. + zoneminder-common - Common files that do not differ based on the web server + zoneminder-httpd - Files needed for compatibility with the Apache web server + zoneminder-nginx - Files needed for compatibility with the Nginx web server + + You can switch between different subpackages with dnf/yum. Be advised that, + if you modified any of the default config files supplied by the package, + rpm may not update the config file to the proper version. This is by design. + Use drop-in files instead, to avoid this issue. + +4. Continue on to the next README that corresponds to the chosen webserver: + + README.httpd - Follow these steps when using Apache + README.nginx - Follow these steps when using Nginx diff --git a/distros/redhat/nginx/README.Fedora b/distros/redhat/readme/README.nginx similarity index 100% rename from distros/redhat/nginx/README.Fedora rename to distros/redhat/readme/README.nginx diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 27cc59ba9..839c9366f 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -1,3 +1,4 @@ +# Leaving this to allow one to build zoneminder-http subpackage using arbitrary user account %global zmuid_final apache %global zmgid_final apache @@ -7,10 +8,6 @@ # CakePHP-Enum-Behavior is configured as a git submodule %global ceb_version 1.0-zm -%if "%{zmuid_final}" == "nginx" -%global with_nginx 1 -%endif - %global sslcert %{_sysconfdir}/pki/tls/certs/localhost.crt %global sslkey %{_sysconfdir}/pki/tls/private/localhost.key @@ -22,11 +19,12 @@ %global with_apcu_bc 1 %endif +# The default for everything but el7 these days %global _hardened_build 1 Name: zoneminder Version: 1.32.2 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons # Mootools is inder the MIT license: http://mootools.net/ @@ -74,6 +72,7 @@ BuildRequires: vlc-devel BuildRequires: libcurl-devel BuildRequires: libv4l-devel BuildRequires: desktop-file-utils +BuildRequires: gzip # ZoneMinder looks for and records the location of the ffmpeg binary during build BuildRequires: ffmpeg @@ -83,10 +82,25 @@ BuildRequires: ffmpeg-devel BuildRequires: libmp4v2-devel BuildRequires: x264-devel -%{?with_nginx:Requires: nginx} -%{?with_nginx:Requires: php-fpm} -%{!?with_nginx:Requires: httpd} -%{!?with_nginx:Requires: php} +# Allow existing user base to seamlessly transition to sub-packages +Requires: %{name}-common%{?_isa} = %{version}-%{release} +Requires: %{name}-httpd%{?_isa} = %{version}-%{release} + +%description +ZoneMinder is a set of applications which is intended to provide a complete +solution allowing you to capture, analyze, record and monitor any cameras you +have attached to a Linux based machine. It is designed to run on kernels which +support the Video For Linux (V4L) interface and has been tested with cameras +attached to BTTV cards, various USB cameras and IP network cameras. It is +designed to support as many cameras as you can attach to your computer without +too much degradation of performance. + +This is a meta package for backwards compatibility with the existing +ZoneMinder user base. + +%package common +Summary: Common files for ZoneMinder, not tied to a specific web server + Requires: php-mysqli Requires: php-common Requires: php-gd @@ -111,16 +125,12 @@ Requires: perl(Net::FTP) Requires: perl(LWP::Protocol::https) Requires: ca-certificates Requires: zip - -Requires(post): systemd -Requires(post): systemd-sysv -Requires(preun): systemd -Requires(postun): systemd +%{systemd_requires} Requires(post): %{_bindir}/gpasswd Requires(post): %{_bindir}/less -%description +%description common ZoneMinder is a set of applications which is intended to provide a complete solution allowing you to capture, analyze, record and monitor any cameras you have attached to a Linux based machine. It is designed to run on kernels which @@ -129,15 +139,56 @@ attached to BTTV cards, various USB cameras and IP network cameras. It is designed to support as many cameras as you can attach to your computer without too much degradation of performance. +This is a meta-package that exists solely to allow the existing user base to +seamlessly transition to sub-packages. + +%package httpd +Summary: ZoneMinder configuration for Apache web server +Requires: %{name}-common%{?_isa} = %{version}-%{release} +Requires: httpd +Requires: php + +Conflicts: %{name}-nginx + +%description httpd +ZoneMinder is a set of applications which is intended to provide a complete +solution allowing you to capture, analyze, record and monitor any cameras you +have attached to a Linux based machine. It is designed to run on kernels which +support the Video For Linux (V4L) interface and has been tested with cameras +attached to BTTV cards, various USB cameras and IP network cameras. It is +designed to support as many cameras as you can attach to your computer without +too much degradation of performance. + +This sub-package contains configuration specific to Apache web server + +%package nginx +Summary: ZoneMinder configuration for Nginx web server +Requires: %{name}-common%{?_isa} = %{version}-%{release} +Requires: nginx +Requires: php-fpm + +Conflicts: %{name}-httpd + +%description nginx +ZoneMinder is a set of applications which is intended to provide a complete +solution allowing you to capture, analyze, record and monitor any cameras you +have attached to a Linux based machine. It is designed to run on kernels which +support the Video For Linux (V4L) interface and has been tested with cameras +attached to BTTV cards, various USB cameras and IP network cameras. It is +designed to support as many cameras as you can attach to your computer without +too much degradation of performance. + +This sub-package contains support for ZoneMinder with the Nginx web server + %prep %autosetup -p 1 -a 1 -%{__rm} -rf ./web/api/app/Plugin/Crud -%{__mv} -f crud-%{crud_version} ./web/api/app/Plugin/Crud +rm -rf ./web/api/app/Plugin/Crud +mv -f crud-%{crud_version} ./web/api/app/Plugin/Crud # The all powerful autosetup macro does not work after the second source tarball -%{__gzip} -dc %{_sourcedir}/cakephp-enum-behavior-%{ceb_version}.tar.gz | tar -xvvf - -%{__rm} -rf ./web/api/app/Plugin/CakePHP-Enum-Behavior -%{__mv} -f CakePHP-Enum-Behavior-%{ceb_version} ./web/api/app/Plugin/CakePHP-Enum-Behavior +gzip -dc %{_sourcedir}/cakephp-enum-behavior-%{ceb_version}.tar.gz | tar -xvvf - +rm -rf ./web/api/app/Plugin/CakePHP-Enum-Behavior +mv -f CakePHP-Enum-Behavior-%{ceb_version} ./web/api/app/Plugin/CakePHP-Enum-Behavior # Change the following default values ./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes @@ -150,7 +201,7 @@ too much degradation of performance. %build %cmake \ -DZM_WEB_USER="%{zmuid_final}" \ - -DZM_WEB_GROUP="%{zmuid_final}" \ + -DZM_WEB_GROUP="%{zmgid_final}" \ -DZM_TARGET_DISTRO="%{zmtargetdistro}" \ . @@ -172,10 +223,13 @@ find %{buildroot} \( -name .htaccess -or -name .editorconfig -or -name .packlist find %{buildroot}%{_datadir}/zoneminder/www/api \( -name cake -or -name cake.php \) -type f -exec sed -i 's\^#!/usr/bin/env bash$\#!%{_buildshell}\' {} \; -exec %{__chmod} 755 {} \; # Use the system cacert file rather then the one bundled with CakePHP -%{__rm} -f %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem -%{__ln_s} ../../../../../../../..%{_sysconfdir}/pki/tls/certs/ca-bundle.crt %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem +rm -f %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem +ln -s ../../../../../../../..%{_sysconfdir}/pki/tls/certs/ca-bundle.crt %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem -%post +# Handle the polkit file differently for web server agnostic support (see post) +rm -f %{buildroot}%{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules + +%post common # Initial installation if [ $1 -eq 1 ] ; then %systemd_post %{name}.service @@ -183,28 +237,38 @@ fi # Upgrade from a previous version of zoneminder if [ $1 -eq 2 ] ; then - # Add any new PTZ control configurations to the database (will not overwrite) %{_bindir}/zmcamtool.pl --import >/dev/null 2>&1 || : # Freshen the database %{_bindir}/zmupdate.pl -f >/dev/null 2>&1 || : - - # We can't run this automatically when new sql account permissions need to - # be manually added first - # Run zmupdate non-interactively - # zmupdate.pl --nointeractive fi -# Allow zoneminder access to local video sources, serial ports, and x10 -%{_bindir}/gpasswd -a %{zmuid_final} video >/dev/null 2>&1 || : -%{_bindir}/gpasswd -a %{zmuid_final} dialout >/dev/null 2>&1 || : - # Warn the end user to read the README file echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README file\nto finish the installation or upgrade!" echo -e "\nThe README file is located here: %{_pkgdocdir}/README\n" -%if 0%{?with_nginx} +%post httpd +ln -s %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.apache %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules +# backwards compatibility +ln -s %{_sysconfdir}/zm/www/zoneminder.apache.conf %{_sysconfdir}/zm/www/zoneminder.conf + +# Allow zoneminder access to local video sources, serial ports, and x10 +%{_bindir}/gpasswd -a %{zmuid_final} video >/dev/null 2>&1 || : +%{_bindir}/gpasswd -a %{zmuid_final} dialout >/dev/null 2>&1 || : + +%post nginx + +ln -s %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules + +# +# TO-DO: configure the README's +# + +# Allow zoneminder access to local video sources, serial ports, and x10 +%{_bindir}/gpasswd -a nginx video >/dev/null 2>&1 || : +%{_bindir}/gpasswd -a nginx dialout >/dev/null 2>&1 || : + # Nginx does not create an SSL certificate like the apache package does so lets do that here if [ -f %{sslkey} -o -f %{sslcert} ]; then exit 0 @@ -230,7 +294,6 @@ SomeOrganizationalUnit ${FQDN} root@${FQDN} EOF -%endif %preun %systemd_preun %{name}.service @@ -238,17 +301,10 @@ EOF %postun %systemd_postun_with_restart %{name}.service -%triggerun -- zoneminder < 1.25.0-4 -# Save the current service runlevel info -# User must manually run systemd-sysv-convert --apply zoneminder -# to migrate them to systemd targets -%{_bindir}/systemd-sysv-convert --save zoneminder >/dev/null 2>&1 ||: - -# Run these because the SysV package being removed won't do them -/sbin/chkconfig --del zoneminder >/dev/null 2>&1 || : -/bin/systemctl try-restart zoneminder.service >/dev/null 2>&1 || : - %files +# nothing + +%files common %license COPYING %doc AUTHORS README.md distros/redhat/readme/README distros/redhat/readme/README.https @@ -260,18 +316,12 @@ EOF # Config folder contents contain sensitive info # and should not be readable by normal users %{_sysconfdir}/zm/conf.d/README -%config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/zm.conf -%config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/*.conf -%ghost %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/zmcustom.conf -%config(noreplace) %attr(644,root,root) %{_sysconfdir}/zm/www/zoneminder.conf -%config(noreplace) %{_sysconfdir}/zm/www/zoneminder.php-fpm.conf %config(noreplace) %{_sysconfdir}/logrotate.d/zoneminder %{_tmpfilesdir}/zoneminder.conf %{_unitdir}/zoneminder.service %{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy -%{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules %{_bindir}/zmsystemctl.pl %{_bindir}/zma @@ -304,6 +354,15 @@ EOF %{_datadir}/zoneminder/ %{_datadir}/applications/*zoneminder.desktop +%files httpd +%config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/zm.conf +%config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/0*.conf +%ghost %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/zmcustom.conf +%config(noreplace) %{_sysconfdir}/zm/www/zoneminder.apache.conf +%config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.apache +%ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules + +%{_unitdir}/zoneminder.service.d/zm-apache.conf %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/events %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/images @@ -313,9 +372,33 @@ EOF %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/cache/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/log/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/spool/zoneminder-upload -%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/run/zoneminder + +%files nginx +%config(noreplace) %attr(640,root,nginx) %{_sysconfdir}/zm/zm.conf +%config(noreplace) %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/*.conf +%ghost %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/zmcustom.conf +%config(noreplace) %{_sysconfdir}/zm/www/zoneminder.nginx.conf +%config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx +%ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules + +%config(noreplace) %{_sysconfdir}/php-fpm.d/zoneminder.php-fpm.conf + + +%{_unitdir}/zoneminder.service.d/zm-nginx.conf +%dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder +%dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/events +%dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/images +%dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/sock +%dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/swap +%dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/temp +%dir %attr(755,nginx,nginx) %{_localstatedir}/cache/zoneminder +%dir %attr(755,nginx,nginx) %{_localstatedir}/log/zoneminder +%dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload %changelog +* Wed Nov 14 2018 Andrew Bauer - 1.32.2-2 +- Break into sub-packages + * Sat Oct 13 2018 Andrew Bauer - 1.32.2-1 - 1.32.2 release - Bug fix release From d06e1b075ddf22f9a36a4254196d5e0aa315b7f7 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 10:47:53 -0600 Subject: [PATCH 115/240] fix filename of com.zoneminder.systemctl.rules.nginx --- distros/redhat/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index bf4e2b40d..4c9abb6fa 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -35,7 +35,7 @@ configure_file(nginx/zoneminder.nginx.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zonemi configure_file(nginx/zoneminder.nginx.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.tmpfiles.conf @ONLY) configure_file(nginx/zm-web-user.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-web-user.conf COPYONLY) configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) -configure_file(nginx/com.zoneminder.systemctl.rules.nginx.in ${CMAKE_CURRENT_SOURCE_DIR}/com.zoneminder.systemctl.rules.nginx COPYONLY) +configure_file(nginx/com.zoneminder.systemctl.rules.nginx ${CMAKE_CURRENT_SOURCE_DIR}/com.zoneminder.systemctl.rules.nginx COPYONLY) # # INSTALLATION STAGE From 7f7fc44b032a528c6be047b5a874dbbeb899f5dd Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 11:01:12 -0600 Subject: [PATCH 116/240] fix nameing of tmpfiles config --- distros/redhat/zoneminder.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 839c9366f..961884921 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -319,7 +319,6 @@ EOF %config(noreplace) %{_sysconfdir}/logrotate.d/zoneminder -%{_tmpfilesdir}/zoneminder.conf %{_unitdir}/zoneminder.service %{_datadir}/polkit-1/actions/com.zoneminder.systemctl.policy %{_bindir}/zmsystemctl.pl @@ -363,6 +362,7 @@ EOF %ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules %{_unitdir}/zoneminder.service.d/zm-apache.conf +%{_tmpfilesdir}/zoneminder.apache.tmpfiles.conf %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/events %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/images @@ -385,6 +385,7 @@ EOF %{_unitdir}/zoneminder.service.d/zm-nginx.conf +%{_tmpfilesdir}/zoneminder.nginx.tmpfiles.conf %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/events %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/images From f79a7e49a817aed4226aef87b10eced6432f5d74 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 11:32:35 -0600 Subject: [PATCH 117/240] rpm subpackages - additional fixes --- distros/redhat/apache/zm-apache.conf.in | 2 +- distros/redhat/common/zoneminder.service.in | 2 -- distros/redhat/zoneminder.spec | 12 ++++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/distros/redhat/apache/zm-apache.conf.in b/distros/redhat/apache/zm-apache.conf.in index edf3a090d..1a00d8d9b 100644 --- a/distros/redhat/apache/zm-apache.conf.in +++ b/distros/redhat/apache/zm-apache.conf.in @@ -1,4 +1,4 @@ -# Additional config directions for ZoneMinder with Apache web server +# Additional config directives for ZoneMinder with Apache web server [Unit] After=httpd.service diff --git a/distros/redhat/common/zoneminder.service.in b/distros/redhat/common/zoneminder.service.in index 540c2f939..8551a60e2 100644 --- a/distros/redhat/common/zoneminder.service.in +++ b/distros/redhat/common/zoneminder.service.in @@ -7,8 +7,6 @@ After=network.target mariadb.service Requires=mariadb.service [Service] -User=@WEB_USER@ -Group=@WEB_GROUP@ Type=forking ExecStart=@BINDIR@/zmpkg.pl start ExecReload=@BINDIR@/zmpkg.pl restart diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 961884921..55906516c 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -246,12 +246,12 @@ fi # Warn the end user to read the README file echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README file\nto finish the installation or upgrade!" -echo -e "\nThe README file is located here: %{_pkgdocdir}/README\n" +echo -e "\nThe README file is located here: %{_pkgdocdir}-common/README\n" %post httpd -ln -s %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.apache %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules +ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.apache %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility -ln -s %{_sysconfdir}/zm/www/zoneminder.apache.conf %{_sysconfdir}/zm/www/zoneminder.conf +ln -sf %{_sysconfdir}/zm/www/zoneminder.apache.conf %{_sysconfdir}/zm/www/zoneminder.conf # Allow zoneminder access to local video sources, serial ports, and x10 %{_bindir}/gpasswd -a %{zmuid_final} video >/dev/null 2>&1 || : @@ -259,7 +259,9 @@ ln -s %{_sysconfdir}/zm/www/zoneminder.apache.conf %{_sysconfdir}/zm/www/zonemin %post nginx -ln -s %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules +ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules +# backwards compatibility +ln -sf %{_sysconfdir}/zm/www/zoneminder.nginx.conf %{_sysconfdir}/zm/www/zoneminder.conf # # TO-DO: configure the README's @@ -358,6 +360,7 @@ EOF %config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/0*.conf %ghost %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/zmcustom.conf %config(noreplace) %{_sysconfdir}/zm/www/zoneminder.apache.conf +%ghost %{_sysconfdir}/zm/www/zoneminder.conf %config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.apache %ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules @@ -378,6 +381,7 @@ EOF %config(noreplace) %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/*.conf %ghost %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/zmcustom.conf %config(noreplace) %{_sysconfdir}/zm/www/zoneminder.nginx.conf +%ghost %{_sysconfdir}/zm/www/zoneminder.conf %config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules From 719bdf1270d8bf69377eb75c361f2b5b6e0eb8af Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 11:52:04 -0600 Subject: [PATCH 118/240] rpm subpackages - add readme's --- distros/redhat/readme/README | 12 +- distros/redhat/readme/README.Redhat7 | 175 ------------------ .../readme/{README.Fedora => README.httpd} | 21 +-- distros/redhat/readme/README.nginx | 39 +--- distros/redhat/zoneminder.spec | 3 +- 5 files changed, 21 insertions(+), 229 deletions(-) delete mode 100644 distros/redhat/readme/README.Redhat7 rename distros/redhat/readme/{README.Fedora => README.httpd} (90%) diff --git a/distros/redhat/readme/README b/distros/redhat/readme/README index e25001863..ee7eb66a6 100644 --- a/distros/redhat/readme/README +++ b/distros/redhat/readme/README @@ -21,9 +21,17 @@ What's New You can switch between different subpackages with dnf/yum. Be advised that, if you modified any of the default config files supplied by the package, rpm may not update the config file to the proper version. This is by design. - Use drop-in files instead, to avoid this issue. + To avoid this issue, use drop-in files instead. -4. Continue on to the next README that corresponds to the chosen webserver: +4. If you have installed ZoneMinder from the FedBerry repositories, this build + of ZoneMinder has support for Raspberry Pi hardware acceleration when using + ffmpeg. Unforunately, there is a problem with the same hardware acceleration + when using libvlc. Consequently, libvlc support in this build of ZoneMinder + has been disabled until the problem is resolved. See the following bug + report for details: https://trac.videolan.org/vlc/ticket/18594 + +5. Continue on to the next README that corresponds to the chosen webserver: README.httpd - Follow these steps when using Apache README.nginx - Follow these steps when using Nginx + diff --git a/distros/redhat/readme/README.Redhat7 b/distros/redhat/readme/README.Redhat7 deleted file mode 100644 index c78d02042..000000000 --- a/distros/redhat/readme/README.Redhat7 +++ /dev/null @@ -1,175 +0,0 @@ -What's New -========== - -1. See the ZoneMinder release notes for a list of new features: - https://github.com/ZoneMinder/zoneminder/releases - -2. The contents of the ZoneMinder Apache config file have changed. In - addition, this ZoneMinder package now requires you to manually symlink the - ZoneMinder Apache config file. See new install step 6 and upgrade step 3 - below for details. - -New installs -============ - -1. Unless you are already using MariaDB server, you need to ensure that the - server is configured to start during boot and properly secured by running: - - sudo yum install mariadb-server - sudo systemctl enable mariadb - sudo systemctl start mariadb.service - mysql_secure_installation - -2. Using the password for the root account set during the previous step, you - will need to create the ZoneMinder database and configure a database - account for ZoneMinder to use: - - mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql - mysql -uroot -p -e "grant all on zm.* to \ - 'zmuser'@localhost identified by 'zmpass';" - mysqladmin -uroot -p reload - - The database account credentials, zmuser/zmpass, are arbitrary. Set them to - anything that suits your environment. - -3. If you have chosen to change the zoneminder database account credentials to - something other than zmuser/zmpass, you must now create a config file under - /etc/zm/conf.d and set your credentials there. For example, create the file - /etc/zm/conf.d/zm-db-user.conf and add the following content to it: - - ZM_DB_USER = {username of the sql account you want to use} - ZM_DB_PASS = {password of the sql account you want to use} - - Once the file has been saved, set proper file & ownership permissions on it: - - sudo chown root:apache *.conf - sudo chmod 640 *.conf - -4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local - timezone. PHP will complain loudly if this is not set, or if it is set - incorrectly, and these complaints will show up in the zoneminder logging - system as errors. - - If you are not sure of the proper timezone specification to use, look at - http://php.net/date.timezone - -5. Disable SELinux - - We currently do not have the resources to create and maintain an accurate - SELinux policy for ZoneMinder on CentOS 7. We will gladly accept pull - reqeusts from anyone who wishes to do the work. In the meantime, SELinux - will need to be disabled or put into permissive mode. - - To immediately disbale SELinux for the current seesion, issue the following - from the command line: - - sudo setenforce 0 - - To permanently disable SELinux, edit /etc/selinux/config and change the - SELINUX line from "enforcing" to "disabled". This change will take - effect after a reboot. - -6. Configure the web server - - This package uses the HTTPS protocol by default to access the web portal, - using the default self signed certificate on your system. Requests using - HTTP will auto-redirect to HTTPS. - - Inspect the web server configuration file and verify it meets your needs: - - /etc/zm/www/zoneminder.conf - - If you are running other web enabled services then you may need to edit - this file to suite. See README.https to learn about other alternatives. - - When in doubt, proceed with the default: - - sudo ln -s /etc/zm/www/zoneminder.conf /etc/httpd/conf.d/ - sudo yum install mod_ssl - -7. Now start the web server: - - sudo systemctl enable httpd - sudo systemctl start httpd - -8. Now start zoneminder: - - sudo systemctl enable zoneminder - sudo systemctl start zoneminder - -9. Optionally configure the firewall - - All Redhat distros ship with the firewall enabled. That means you will not - be able to access the ZoneMinder web console from a remote machine until - changes are made to the firewall. - - What follows are a set of minimal commands to allow remote access to the - ZoneMinder web console and also allow ZoneMinder's ONVIF discovery to - work. The following commands do not put any restrictions on which remote - machine(s) have access to the listed ports or services. - - sudo firewall-cmd --permanent --zone=public --add-service=http - sudo firewall-cmd --permanent --zone=public --add-service=https - sudo firewall-cmd --permanent --zone=public --add-port=3702/udp - sudo firewall-cmd --reload - - Additional changes to the firewall may be required, depending on your - security requirements and how you use the system. It is up to you to verify - these commands are sufficient. - -10. Access the ZoneMinder web console - - You may now access the ZoneMinder web console from your web browser using - an appropriate url. Here are some examples: - - http://localhost/zm (works from the local machine only) - http://{machine name}/zm (works only if dns is configured for your network) - http://{ip address}/zm - -Upgrades -======== - -1. Conf.d folder support has been added to ZoneMinder. Any custom - changes previously made to zm.conf must now be made in one or more custom - config files, created under the conf.d folder. Do this now. See - /etc/zm/conf.d/README for details. Once you recreate any custom config changes - under the conf.d folder, they will remain in place indefinitely. - -2. Verify permissions of the zmuser account. - - Over time, the database account permissions required for normal operation - have increased. Verify the zmuser database account has been granted all - permission to the ZoneMinder database: - - mysql -uroot -p -e "show grants for zmuser@localhost;" - - See step 2 of the Installation section to add missing permissions. - -3. Verify the ZoneMinder Apache configuration file in the folder - /etc/zm/www. You will have a file called "zoneminder.conf" and there - may also be a file called "zoneminder.conf.rpmnew". If an rpmnew file - exists, inspect it and merge anything new in that file with zoneminder.conf. - Verify the SSL REquirements meet your needs. Read README.https if necessary. - - The contents of this file must be merged into your Apache configuration. - See step 6 of the installation section if you have not already done this - during a previous upgrade. - -4. Upgrade the database before starting ZoneMinder. - - Most upgrades can be performed by executing the following command: - - sudo zmupdate.pl - - Recent versions of ZoneMinder don't require any parameters added to the - zmupdate command. However, if ZoneMinder complains, you may need to call - zmupdate in the following manner: - - sudo zmupdate.pl --user=root --pass= --version= - -5. Now restart the web server then start zoneminder: - - sudo systemctl restart httpd - sudo systemctl start zoneminder - - diff --git a/distros/redhat/readme/README.Fedora b/distros/redhat/readme/README.httpd similarity index 90% rename from distros/redhat/readme/README.Fedora rename to distros/redhat/readme/README.httpd index 9c5061e28..d85fe7c27 100644 --- a/distros/redhat/readme/README.Fedora +++ b/distros/redhat/readme/README.httpd @@ -1,17 +1,8 @@ -What's New -========== - -1. See the ZoneMinder release notes for a list of new features: - https://github.com/ZoneMinder/zoneminder/releases - -2. The contents of the ZoneMinder Apache config file have changed. In - addition, this ZoneMinder package now requires you to manually symlink the - ZoneMinder Apache config file. See new install step 6 and upgrade step 3 - below for details. - New installs ============ +NOTE: EL7 users should replace "dnf" with "yum" in the instructions below. + 1. Unless you are already using MariaDB server, you need to ensure that the server is configured to start during boot and properly secured by running: @@ -77,14 +68,14 @@ New installs Inspect the web server configuration file and verify it meets your needs: - /etc/zm/www/zoneminder.conf + /etc/zm/www/zoneminder.apache.conf If you are running other web enabled services then you may need to edit this file to suite. See README.https to learn about other alternatives. When in doubt, proceed with the default: - sudo ln -s /etc/zm/www/zoneminder.conf /etc/httpd/conf.d/ + sudo ln -s /etc/zm/www/zoneminder.apache.conf /etc/httpd/conf.d/ sudo dnf install mod_ssl 7. Now start the web server: @@ -146,8 +137,8 @@ Upgrades See step 2 of the Installation section to add missing permissions. 3. Verify the ZoneMinder Apache configuration file in the folder - /etc/zm/www. You will have a file called "zoneminder.conf" and there - may also be a file called "zoneminder.conf.rpmnew". If the rpmnew file + /etc/zm/www. You will have a file called "zoneminder.apache.conf" and there + may also be one or more files with "rpmnew" extenstion. If the rpmnew file exists, inspect it and merge anything new in that file with zoneminder.conf. Verify the SSL REquirements meet your needs. Read README.https if necessary. diff --git a/distros/redhat/readme/README.nginx b/distros/redhat/readme/README.nginx index 90d760952..5f425a2df 100644 --- a/distros/redhat/readme/README.nginx +++ b/distros/redhat/readme/README.nginx @@ -1,24 +1,3 @@ -What's New -========== - -1. See the ZoneMinder release notes for a list of new features: - https://github.com/ZoneMinder/zoneminder/releases - -2. The contents of the ZoneMinder Apache config file have changed. In - addition, this ZoneMinder package now requires you to manually symlink the - ZoneMinder Apache config file. See new install step 6 and upgrade step 3 - below for details. - -3. This is an experimental build of ZoneMinder supporting nginx, rather than - apache web server. - -4. If you have installed ZoneMinder from the FedBerry repositories, this build - of ZoneMinder has support for Raspberry Pi hardware acceleration when using - ffmpeg. Unforunately, there is a problem with the same hardware acceleration - when using libvlc. Consequently, libvlc support in this build of ZoneMinder - has been disabled until the problem is resolved. See the following bug - report for details: https://trac.videolan.org/vlc/ticket/18594 - New installs ============ @@ -52,7 +31,7 @@ New installs Once the file has been saved, set proper file & ownership permissions on it: - sudo chown root:apache *.conf + sudo chown root:nginx *.conf sudo chmod 640 *.conf 4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local @@ -96,19 +75,7 @@ New installs sudo ln -s /etc/zm/www/zoneminder.conf /etc/nginx/default.d/ -7. Fcgiwrap is required when using ZoneMinder with Nginx. At the time of this - writing, fcgiwrap is not yet available in the Fedora repos. Until it - becomes available, you may install it from my Copr repository: - - https://copr.fedorainfracloud.org/coprs/kni/fcgiwrap/ - - Follow the intructions on that site to enable the repo. Once enabled, - install fcgiwrap: - - sudo dnf install fcgiwrap - - After fcgiwrap is installed, it must be configured. Edit - /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of +7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of simulatneous streams the server should support. Generally, a good minimum value for this equals the total number of cameras you expect to view at the same time. @@ -193,7 +160,7 @@ Upgrades sudo zmupdate.pl --user=root --pass= --version= -5. Now restart nginx and php-fpm then start and zoneminder: +5. Now restart nginx and php-fpm then start zoneminder: sudo systemctl restart nginx sudo systemctl restart php-fpm diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 55906516c..f75339706 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -166,6 +166,7 @@ Summary: ZoneMinder configuration for Nginx web server Requires: %{name}-common%{?_isa} = %{version}-%{release} Requires: nginx Requires: php-fpm +Requires: fcgiwrap Conflicts: %{name}-httpd @@ -308,7 +309,7 @@ EOF %files common %license COPYING -%doc AUTHORS README.md distros/redhat/readme/README distros/redhat/readme/README.https +%doc AUTHORS README.md distros/redhat/readme/README distros/redhat/readme/README.httpd distros/redhat/readme/README.nginx distros/redhat/readme/README.https # We want these two folders to have "normal" read permission # compared to the folder contents From d3f45120f11aee40275bc338909c53b5dc9c1529 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 15:25:51 -0600 Subject: [PATCH 119/240] Update zoneminder.apache.tmpfiles.in --- distros/redhat/apache/zoneminder.apache.tmpfiles.in | 1 + 1 file changed, 1 insertion(+) diff --git a/distros/redhat/apache/zoneminder.apache.tmpfiles.in b/distros/redhat/apache/zoneminder.apache.tmpfiles.in index 21e6119fe..2d32de766 100644 --- a/distros/redhat/apache/zoneminder.apache.tmpfiles.in +++ b/distros/redhat/apache/zoneminder.apache.tmpfiles.in @@ -3,3 +3,4 @@ D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_CACHEDIR@ 0755 @WEB_USER@ @WEB_GROUP@ d @ZM_DIR_EVENTS@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_DIR_IMAGES@ 0755 @WEB_USER@ @WEB_GROUP@ +D /var/lib/php/session 770 root @WEB_GROUP@ From f9b61114e2d328c89a9b028a7f754e549c8e19a9 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 15:33:52 -0600 Subject: [PATCH 120/240] Update zoneminder.apache.tmpfiles.in --- distros/redhat/apache/zoneminder.apache.tmpfiles.in | 1 + 1 file changed, 1 insertion(+) diff --git a/distros/redhat/apache/zoneminder.apache.tmpfiles.in b/distros/redhat/apache/zoneminder.apache.tmpfiles.in index 2d32de766..e9e68c2e7 100644 --- a/distros/redhat/apache/zoneminder.apache.tmpfiles.in +++ b/distros/redhat/apache/zoneminder.apache.tmpfiles.in @@ -4,3 +4,4 @@ D @ZM_CACHEDIR@ 0755 @WEB_USER@ @WEB_GROUP@ d @ZM_DIR_EVENTS@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_DIR_IMAGES@ 0755 @WEB_USER@ @WEB_GROUP@ D /var/lib/php/session 770 root @WEB_GROUP@ +D /var/lib/php/wsdlcache 770 root @WEB_GROUP@ From abd178d4213cf8d45757db95249d4b16fc2beb88 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 19:46:15 -0600 Subject: [PATCH 121/240] rpm pkg - add nginx to apache group, rather than set folder perms --- distros/redhat/apache/zoneminder.apache.tmpfiles.in | 3 +-- distros/redhat/nginx/zoneminder.nginx.tmpfiles.in | 2 -- distros/redhat/zoneminder.spec | 8 ++++---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/distros/redhat/apache/zoneminder.apache.tmpfiles.in b/distros/redhat/apache/zoneminder.apache.tmpfiles.in index e9e68c2e7..f24babdc6 100644 --- a/distros/redhat/apache/zoneminder.apache.tmpfiles.in +++ b/distros/redhat/apache/zoneminder.apache.tmpfiles.in @@ -3,5 +3,4 @@ D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_CACHEDIR@ 0755 @WEB_USER@ @WEB_GROUP@ d @ZM_DIR_EVENTS@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_DIR_IMAGES@ 0755 @WEB_USER@ @WEB_GROUP@ -D /var/lib/php/session 770 root @WEB_GROUP@ -D /var/lib/php/wsdlcache 770 root @WEB_GROUP@ + diff --git a/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in b/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in index 46dbd99fe..1c581fcb9 100644 --- a/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in +++ b/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in @@ -3,6 +3,4 @@ D @ZM_SOCKDIR@ 0755 nginx nginx D @ZM_CACHEDIR@ 0755 nginx nginx d @ZM_DIR_EVENTS@ 0755 nginx nginx D @ZM_DIR_IMAGES@ 0755 nginx nginx -D /var/lib/php/session 770 root nginx -D /var/lib/php/wsdlcache 770 root nginx diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index f75339706..a63d7a914 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -260,14 +260,14 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.apache.conf %{_sysconfdir}/zm/www/zonemi %post nginx +# Php package owns the session folder and sets group ownership to apache account +# We could override the folder permission, but adding nginx to the apache group works better +%{_bindir}/gpasswd -a nginx apache >/dev/null 2>&1 || : + ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility ln -sf %{_sysconfdir}/zm/www/zoneminder.nginx.conf %{_sysconfdir}/zm/www/zoneminder.conf -# -# TO-DO: configure the README's -# - # Allow zoneminder access to local video sources, serial ports, and x10 %{_bindir}/gpasswd -a nginx video >/dev/null 2>&1 || : %{_bindir}/gpasswd -a nginx dialout >/dev/null 2>&1 || : From 4144fe3292dbfdafd7fb9c0e8a0c0e7981c80900 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 17 Nov 2018 21:41:25 -0600 Subject: [PATCH 122/240] rpm pkg - fix php-fpm config --- distros/redhat/CMakeLists.txt | 2 +- .../{zoneminder.php-fpm.conf.in => zoneminder.php-fpm.conf} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename distros/redhat/nginx/{zoneminder.php-fpm.conf.in => zoneminder.php-fpm.conf} (91%) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index 4c9abb6fa..ba5908d5d 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -34,7 +34,7 @@ configure_file(nginx/zm-nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-nginx.conf COP configure_file(nginx/zoneminder.nginx.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.conf @ONLY) configure_file(nginx/zoneminder.nginx.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.tmpfiles.conf @ONLY) configure_file(nginx/zm-web-user.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-web-user.conf COPYONLY) -configure_file(nginx/zoneminder.php-fpm.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf @ONLY) +configure_file(nginx/zoneminder.php-fpm.conf ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf COPYONLY) configure_file(nginx/com.zoneminder.systemctl.rules.nginx ${CMAKE_CURRENT_SOURCE_DIR}/com.zoneminder.systemctl.rules.nginx COPYONLY) # diff --git a/distros/redhat/nginx/zoneminder.php-fpm.conf.in b/distros/redhat/nginx/zoneminder.php-fpm.conf similarity index 91% rename from distros/redhat/nginx/zoneminder.php-fpm.conf.in rename to distros/redhat/nginx/zoneminder.php-fpm.conf index a4537b236..cd60a5120 100644 --- a/distros/redhat/nginx/zoneminder.php-fpm.conf.in +++ b/distros/redhat/nginx/zoneminder.php-fpm.conf @@ -3,8 +3,8 @@ ; Change the user and group of the default pool to the web server account [www] -user = @WEB_USER@ -group = @WEB_GROUP@ +user = nginx +group = nginx ; These parameters are typically a tradoff between performance and memory ; consumption. See the contents of www.conf for details. From 05c4f586c23c3c1088c7781812870ec10606e841 Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Sun, 18 Nov 2018 10:15:27 -0600 Subject: [PATCH 123/240] rpm pkg - httpd instead of apache --- distros/redhat/CMakeLists.txt | 16 ++++++++-------- .../com.zoneminder.systemctl.rules.httpd.in} | 0 .../zm-apache.conf.in => httpd/zm-httpd.conf.in} | 0 .../zoneminder.httpd.conf.in} | 0 .../zoneminder.httpd.tmpfiles.in} | 0 distros/redhat/zoneminder.spec | 12 ++++++------ 6 files changed, 14 insertions(+), 14 deletions(-) rename distros/redhat/{apache/com.zoneminder.systemctl.rules.apache.in => httpd/com.zoneminder.systemctl.rules.httpd.in} (100%) rename distros/redhat/{apache/zm-apache.conf.in => httpd/zm-httpd.conf.in} (100%) rename distros/redhat/{apache/zoneminder.apache.conf.in => httpd/zoneminder.httpd.conf.in} (100%) rename distros/redhat/{apache/zoneminder.apache.tmpfiles.in => httpd/zoneminder.httpd.tmpfiles.in} (100%) diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index ba5908d5d..716faea4c 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -24,10 +24,10 @@ configure_file(common/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zonemind file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp) # Configure the Apache zoneminder files -configure_file(apache/zm-apache.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zm-apache.conf @ONLY) -configure_file(apache/zoneminder.apache.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.apache.conf @ONLY) -configure_file(apache/zoneminder.apache.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.apache.tmpfiles.conf @ONLY) -configure_file(apache/com.zoneminder.systemctl.rules.apache.in ${CMAKE_CURRENT_SOURCE_DIR}/com.zoneminder.systemctl.rules.apache @ONLY) +configure_file(httpd/zm-httpd.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zm-httpd.conf @ONLY) +configure_file(httpd/zoneminder.httpd.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.httpd.conf @ONLY) +configure_file(httpd/zoneminder.httpd.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.httpd.tmpfiles.conf @ONLY) +configure_file(httpd/com.zoneminder.systemctl.rules.httpd.in ${CMAKE_CURRENT_SOURCE_DIR}/com.zoneminder.systemctl.rules.httpd @ONLY) # Configure the Nginx zoneminder files configure_file(nginx/zm-nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-nginx.conf COPYONLY) @@ -54,10 +54,10 @@ install(DIRECTORY zoneminder-upload DESTINATION /var/spool DIRECTORY_PERMISSIONS install(DIRECTORY events images temp DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # Install the Apache zoneminder files -install(FILES zm-apache.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -install(FILES zoneminder.apache.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -install(FILES zoneminder.apache.tmpfiles.conf DESTINATION /usr/lib/tmpfiles.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) -install(FILES com.zoneminder.systemctl.rules.apache DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zm-httpd.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.httpd.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES zoneminder.httpd.tmpfiles.conf DESTINATION /usr/lib/tmpfiles.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES com.zoneminder.systemctl.rules.httpd DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) # Install the Nginx zoneminder files install(FILES zm-nginx.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/distros/redhat/apache/com.zoneminder.systemctl.rules.apache.in b/distros/redhat/httpd/com.zoneminder.systemctl.rules.httpd.in similarity index 100% rename from distros/redhat/apache/com.zoneminder.systemctl.rules.apache.in rename to distros/redhat/httpd/com.zoneminder.systemctl.rules.httpd.in diff --git a/distros/redhat/apache/zm-apache.conf.in b/distros/redhat/httpd/zm-httpd.conf.in similarity index 100% rename from distros/redhat/apache/zm-apache.conf.in rename to distros/redhat/httpd/zm-httpd.conf.in diff --git a/distros/redhat/apache/zoneminder.apache.conf.in b/distros/redhat/httpd/zoneminder.httpd.conf.in similarity index 100% rename from distros/redhat/apache/zoneminder.apache.conf.in rename to distros/redhat/httpd/zoneminder.httpd.conf.in diff --git a/distros/redhat/apache/zoneminder.apache.tmpfiles.in b/distros/redhat/httpd/zoneminder.httpd.tmpfiles.in similarity index 100% rename from distros/redhat/apache/zoneminder.apache.tmpfiles.in rename to distros/redhat/httpd/zoneminder.httpd.tmpfiles.in diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index a63d7a914..9e4fd2951 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -250,9 +250,9 @@ echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README echo -e "\nThe README file is located here: %{_pkgdocdir}-common/README\n" %post httpd -ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.apache %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules +ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.httpd %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility -ln -sf %{_sysconfdir}/zm/www/zoneminder.apache.conf %{_sysconfdir}/zm/www/zoneminder.conf +ln -sf %{_sysconfdir}/zm/www/zoneminder.httpd.conf %{_sysconfdir}/zm/www/zoneminder.conf # Allow zoneminder access to local video sources, serial ports, and x10 %{_bindir}/gpasswd -a %{zmuid_final} video >/dev/null 2>&1 || : @@ -360,13 +360,13 @@ EOF %config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/zm.conf %config(noreplace) %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/0*.conf %ghost %attr(640,root,%{zmgid_final}) %{_sysconfdir}/zm/conf.d/zmcustom.conf -%config(noreplace) %{_sysconfdir}/zm/www/zoneminder.apache.conf +%config(noreplace) %{_sysconfdir}/zm/www/zoneminder.httpd.conf %ghost %{_sysconfdir}/zm/www/zoneminder.conf -%config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.apache +%config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.httpd %ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules -%{_unitdir}/zoneminder.service.d/zm-apache.conf -%{_tmpfilesdir}/zoneminder.apache.tmpfiles.conf +%{_unitdir}/zoneminder.service.d/zm-httpd.conf +%{_tmpfilesdir}/zoneminder.httpd.tmpfiles.conf %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/events %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/images From 5e2935b81de1ecc1018734db0294b76b75eb623c Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Sun, 18 Nov 2018 11:16:46 -0600 Subject: [PATCH 124/240] rpm pkg - change ownership of php session files --- distros/redhat/zoneminder.spec | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 9e4fd2951..fa188bf28 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -128,7 +128,7 @@ Requires: zip %{systemd_requires} Requires(post): %{_bindir}/gpasswd -Requires(post): %{_bindir}/less +Requires(post): %{_bindir}/chown %description common ZoneMinder is a set of applications which is intended to provide a complete @@ -250,6 +250,9 @@ echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README echo -e "\nThe README file is located here: %{_pkgdocdir}-common/README\n" %post httpd +# For the case of changing from nginx <-> httpd, existing php session files must change ownership +%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/php/session/ >/dev/null 2>&1 || : + ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.httpd %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility ln -sf %{_sysconfdir}/zm/www/zoneminder.httpd.conf %{_sysconfdir}/zm/www/zoneminder.conf @@ -264,6 +267,9 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.httpd.conf %{_sysconfdir}/zm/www/zonemin # We could override the folder permission, but adding nginx to the apache group works better %{_bindir}/gpasswd -a nginx apache >/dev/null 2>&1 || : +# For the case of changing from httpd <-> nginx, existing php session files must change ownership +%{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/php/session/ >/dev/null 2>&1 || : + ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility ln -sf %{_sysconfdir}/zm/www/zoneminder.nginx.conf %{_sysconfdir}/zm/www/zoneminder.conf From ac7a03233e3b3a8a9a38270838e916a11a518497 Mon Sep 17 00:00:00 2001 From: Andy Bauer Date: Sun, 18 Nov 2018 11:20:47 -0600 Subject: [PATCH 125/240] rpm pkg - change owership of log files --- distros/redhat/zoneminder.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index fa188bf28..396c3961b 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -250,8 +250,9 @@ echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README echo -e "\nThe README file is located here: %{_pkgdocdir}-common/README\n" %post httpd -# For the case of changing from nginx <-> httpd, existing php session files must change ownership +# For the case of changing from nginx <-> httpd, these files must change ownership if they exist %{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/php/session/ >/dev/null 2>&1 || : +%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_localstatedir}/log/zoneminder/ >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.httpd %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility @@ -267,8 +268,9 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.httpd.conf %{_sysconfdir}/zm/www/zonemin # We could override the folder permission, but adding nginx to the apache group works better %{_bindir}/gpasswd -a nginx apache >/dev/null 2>&1 || : -# For the case of changing from httpd <-> nginx, existing php session files must change ownership +# For the case of changing from nginx <-> httpd, these files must change ownership if they exist %{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/php/session/ >/dev/null 2>&1 || : +%{_bindir}/chown -R nginx:nginx %{_localstatedir}/log/zoneminder/ >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility From 3b2bac0e41650e205439f41485a01f4763977885 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 18 Nov 2018 11:31:04 -0600 Subject: [PATCH 126/240] rpm pkg - add missing asterisk --- distros/redhat/zoneminder.spec | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 396c3961b..0c94a1f91 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -250,9 +250,9 @@ echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, you must read the README echo -e "\nThe README file is located here: %{_pkgdocdir}-common/README\n" %post httpd -# For the case of changing from nginx <-> httpd, these files must change ownership if they exist -%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/php/session/ >/dev/null 2>&1 || : -%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_localstatedir}/log/zoneminder/ >/dev/null 2>&1 || : +# For the case of changing from nginx <-> httpd, files in these folders must change ownership if they exist +%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/php/session/* >/dev/null 2>&1 || : +%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_localstatedir}/log/zoneminder/* >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.httpd %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility @@ -268,9 +268,9 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.httpd.conf %{_sysconfdir}/zm/www/zonemin # We could override the folder permission, but adding nginx to the apache group works better %{_bindir}/gpasswd -a nginx apache >/dev/null 2>&1 || : -# For the case of changing from nginx <-> httpd, these files must change ownership if they exist -%{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/php/session/ >/dev/null 2>&1 || : -%{_bindir}/chown -R nginx:nginx %{_localstatedir}/log/zoneminder/ >/dev/null 2>&1 || : +# For the case of changing from httpd <-> nginx, files in these folders must change ownership if they exist +%{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/php/session/* >/dev/null 2>&1 || : +%{_bindir}/chown -R nginx:nginx %{_localstatedir}/log/zoneminder/* >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility From 689665cfcc31e3766abef2592fb070e7faf74def Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 18 Nov 2018 11:41:20 -0600 Subject: [PATCH 127/240] rpm pkg - fgciwrap service is instantiated --- distros/redhat/nginx/zm-nginx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/nginx/zm-nginx.conf b/distros/redhat/nginx/zm-nginx.conf index 98ca1943a..5f0319b17 100644 --- a/distros/redhat/nginx/zm-nginx.conf +++ b/distros/redhat/nginx/zm-nginx.conf @@ -2,7 +2,7 @@ [Unit] After=nginx.service php-fpm.service fcgiwrap.service -Requires=php-fpm.service fcgiwrap.service +Requires=php-fpm.service fcgiwrap@nginx.service [Service] User=nginx From d1219791cc29d1112ea300b39ff8cec51b8fe0e1 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 18 Nov 2018 12:30:24 -0600 Subject: [PATCH 128/240] rpm pkg - fix api support in nginx config --- distros/redhat/nginx/zoneminder.nginx.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/nginx/zoneminder.nginx.conf.in b/distros/redhat/nginx/zoneminder.nginx.conf.in index cca9af54f..fb8141c74 100644 --- a/distros/redhat/nginx/zoneminder.nginx.conf.in +++ b/distros/redhat/nginx/zoneminder.nginx.conf.in @@ -47,7 +47,7 @@ location /zm { location /zm/api/ { alias "@ZM_WEBDIR@"; - rewrite ^/zm/api(.+)$ /zm/api/index.php?p=$1 last; + rewrite ^/zm/api(.+)$ /zm/api/app/webroot/index.php?p=$1 last; } } From f867d7552255a5974e4718e39108d40e87c88c29 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 18 Nov 2018 12:48:41 -0600 Subject: [PATCH 129/240] rpm pkg - set ownership of events folder --- distros/redhat/zoneminder.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 0c94a1f91..3ff68b080 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -253,6 +253,7 @@ echo -e "\nThe README file is located here: %{_pkgdocdir}-common/README\n" # For the case of changing from nginx <-> httpd, files in these folders must change ownership if they exist %{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/php/session/* >/dev/null 2>&1 || : %{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_localstatedir}/log/zoneminder/* >/dev/null 2>&1 || : +%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/zoneminder/events/* >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.httpd %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility @@ -271,6 +272,7 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.httpd.conf %{_sysconfdir}/zm/www/zonemin # For the case of changing from httpd <-> nginx, files in these folders must change ownership if they exist %{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/php/session/* >/dev/null 2>&1 || : %{_bindir}/chown -R nginx:nginx %{_localstatedir}/log/zoneminder/* >/dev/null 2>&1 || : +%{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/zoneminder/events/* >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility From fac9d69801679d4aa872bffccf6353ca152a8e47 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 20 Nov 2018 15:36:34 -0600 Subject: [PATCH 130/240] rpm - update README's --- distros/redhat/readme/README.httpd | 6 +++--- distros/redhat/readme/README.https | 7 ++++--- distros/redhat/readme/README.nginx | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/distros/redhat/readme/README.httpd b/distros/redhat/readme/README.httpd index d85fe7c27..6d542107e 100644 --- a/distros/redhat/readme/README.httpd +++ b/distros/redhat/readme/README.httpd @@ -68,14 +68,14 @@ NOTE: EL7 users should replace "dnf" with "yum" in the instructions below. Inspect the web server configuration file and verify it meets your needs: - /etc/zm/www/zoneminder.apache.conf + /etc/zm/www/zoneminder.httpd.conf If you are running other web enabled services then you may need to edit this file to suite. See README.https to learn about other alternatives. When in doubt, proceed with the default: - sudo ln -s /etc/zm/www/zoneminder.apache.conf /etc/httpd/conf.d/ + sudo ln -s /etc/zm/www/zoneminder.httpd.conf /etc/httpd/conf.d/ sudo dnf install mod_ssl 7. Now start the web server: @@ -137,7 +137,7 @@ Upgrades See step 2 of the Installation section to add missing permissions. 3. Verify the ZoneMinder Apache configuration file in the folder - /etc/zm/www. You will have a file called "zoneminder.apache.conf" and there + /etc/zm/www. You will have a file called "zoneminder.httpd.conf" and there may also be one or more files with "rpmnew" extenstion. If the rpmnew file exists, inspect it and merge anything new in that file with zoneminder.conf. Verify the SSL REquirements meet your needs. Read README.https if necessary. diff --git a/distros/redhat/readme/README.https b/distros/redhat/readme/README.https index 4b02aaa0d..620588bf9 100644 --- a/distros/redhat/readme/README.https +++ b/distros/redhat/readme/README.https @@ -20,7 +20,8 @@ experience. to do this: https://wiki.centos.org/HowTos/Https . Additionally, Googling "centos certificate" reveals many articles on the subject. -3. You can turn off HTTPS entirely by simply commenting out the SSLRequireSSL - directives found in /etc/httpd/conf.d/zoneminder.conf. You should also - comment out the HTTP -> HTTPS Rewrite rule. +3. When using Apache, you can turn off HTTPS entirely by simply commenting + out the SSLRequireSSL directives found in + /etc/zm/www/zoneminder.apache.conf. You should also comment out the + HTTP -> HTTPS Rewrite rule. diff --git a/distros/redhat/readme/README.nginx b/distros/redhat/readme/README.nginx index 5f425a2df..f657b668f 100644 --- a/distros/redhat/readme/README.nginx +++ b/distros/redhat/readme/README.nginx @@ -73,7 +73,7 @@ New installs When in doubt, proceed with the default: - sudo ln -s /etc/zm/www/zoneminder.conf /etc/nginx/default.d/ + sudo ln -s /etc/zm/www/zoneminder.nginx.conf /etc/nginx/default.d/ 7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of simulatneous streams the server should support. Generally, a good minimum From fa37da3f1e524a68cc5a30b50ddf6c7fcf5a0928 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 20 Nov 2018 15:47:23 -0600 Subject: [PATCH 131/240] rpm - update README --- distros/redhat/readme/README.httpd | 5 ++++- distros/redhat/readme/README.nginx | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/distros/redhat/readme/README.httpd b/distros/redhat/readme/README.httpd index 6d542107e..6a103819f 100644 --- a/distros/redhat/readme/README.httpd +++ b/distros/redhat/readme/README.httpd @@ -75,7 +75,7 @@ NOTE: EL7 users should replace "dnf" with "yum" in the instructions below. When in doubt, proceed with the default: - sudo ln -s /etc/zm/www/zoneminder.httpd.conf /etc/httpd/conf.d/ + sudo ln -sf /etc/zm/www/zoneminder.httpd.conf /etc/httpd/conf.d/ sudo dnf install mod_ssl 7. Now start the web server: @@ -146,6 +146,9 @@ Upgrades See step 6 of the installation section if you have not already done this during a previous upgrade. + If this step is not performed correctly, the web console will appear + mostly empty and/or significantly corrupted post-upgrade. + 4. Upgrade the database before starting ZoneMinder. Most upgrades can be performed by executing the following command: diff --git a/distros/redhat/readme/README.nginx b/distros/redhat/readme/README.nginx index f657b668f..b55d26428 100644 --- a/distros/redhat/readme/README.nginx +++ b/distros/redhat/readme/README.nginx @@ -73,7 +73,7 @@ New installs When in doubt, proceed with the default: - sudo ln -s /etc/zm/www/zoneminder.nginx.conf /etc/nginx/default.d/ + sudo ln -sf /etc/zm/www/zoneminder.nginx.conf /etc/nginx/default.d/ 7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of simulatneous streams the server should support. Generally, a good minimum From daf813e8771522a28ba05cd1054aead813201b02 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Nov 2018 07:44:35 -0600 Subject: [PATCH 132/240] spelling --- distros/redhat/readme/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/readme/README b/distros/redhat/readme/README index ee7eb66a6..065628321 100644 --- a/distros/redhat/readme/README +++ b/distros/redhat/readme/README @@ -13,7 +13,7 @@ What's New other web servers. Here is a breakdown of the available packages: zoneminder - Meta-package installs zoneminder-common and zoneminder-httpd - This exists soley for backwards compaitilibty. + This exists soley for backwards compatibility. zoneminder-common - Common files that do not differ based on the web server zoneminder-httpd - Files needed for compatibility with the Apache web server zoneminder-nginx - Files needed for compatibility with the Nginx web server From 7ca5fa2ff899d0616da90bf25a01934732b198ed Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 21 Nov 2018 07:58:12 -0600 Subject: [PATCH 133/240] rpm - update README's again --- distros/redhat/readme/README.httpd | 7 +++++-- distros/redhat/readme/README.nginx | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/distros/redhat/readme/README.httpd b/distros/redhat/readme/README.httpd index 6d542107e..5301850df 100644 --- a/distros/redhat/readme/README.httpd +++ b/distros/redhat/readme/README.httpd @@ -75,7 +75,7 @@ NOTE: EL7 users should replace "dnf" with "yum" in the instructions below. When in doubt, proceed with the default: - sudo ln -s /etc/zm/www/zoneminder.httpd.conf /etc/httpd/conf.d/ + sudo ln -sf /etc/zm/www/zoneminder.httpd.conf /etc/httpd/conf.d/ sudo dnf install mod_ssl 7. Now start the web server: @@ -140,12 +140,15 @@ Upgrades /etc/zm/www. You will have a file called "zoneminder.httpd.conf" and there may also be one or more files with "rpmnew" extenstion. If the rpmnew file exists, inspect it and merge anything new in that file with zoneminder.conf. - Verify the SSL REquirements meet your needs. Read README.https if necessary. + Verify the SSL Requirements meet your needs. Read README.https if necessary. The contents of this file must be merged into your Apache configuration. See step 6 of the installation section if you have not already done this during a previous upgrade. + IMPORTANT: Failure to complete this step properly will result in a mostly + empty or significantly corrupted web console post-upgrade. + 4. Upgrade the database before starting ZoneMinder. Most upgrades can be performed by executing the following command: diff --git a/distros/redhat/readme/README.nginx b/distros/redhat/readme/README.nginx index f657b668f..b55d26428 100644 --- a/distros/redhat/readme/README.nginx +++ b/distros/redhat/readme/README.nginx @@ -73,7 +73,7 @@ New installs When in doubt, proceed with the default: - sudo ln -s /etc/zm/www/zoneminder.nginx.conf /etc/nginx/default.d/ + sudo ln -sf /etc/zm/www/zoneminder.nginx.conf /etc/nginx/default.d/ 7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of simulatneous streams the server should support. Generally, a good minimum From 9241c26f2fe0d1201e43e22ed05900c0ecafe9ba Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 12:43:51 -0500 Subject: [PATCH 134/240] Move PATH_MAX to zm_config where all the other defines are --- src/zm.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/zm.h b/src/zm.h index 092561378..ad0f89584 100644 --- a/src/zm.h +++ b/src/zm.h @@ -17,9 +17,6 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -#if !defined(PATH_MAX) -#define PATH_MAX 1024 -#endif #ifndef ZM_H #define ZM_H From 5ad753b6b432773495c1226a6b61fa0e07c5a250 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 12:44:10 -0500 Subject: [PATCH 135/240] zm_comms uses logging functions, so include zm_logger.h --- src/zm_comms.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zm_comms.h b/src/zm_comms.h index 133c0d19f..e93951a85 100644 --- a/src/zm_comms.h +++ b/src/zm_comms.h @@ -20,6 +20,7 @@ #ifndef ZM_COMMS_H #define ZM_COMMS_H +#include "zm_logger.h" #include "zm_exception.h" #include From 48564da9157da9ea37498dfd900493825a5d8815 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 12:44:34 -0500 Subject: [PATCH 136/240] zm_config.h shouldn't include zm.h. zm.h includs zm_config.h --- src/zm_config.h.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/zm_config.h.in b/src/zm_config.h.in index f321095df..87a0f2db4 100644 --- a/src/zm_config.h.in +++ b/src/zm_config.h.in @@ -20,9 +20,11 @@ #ifndef ZM_CONFIG_H #define ZM_CONFIG_H +#if !defined(PATH_MAX) +#define PATH_MAX 1024 +#endif #include "config.h" #include "zm_config_defines.h" -#include "zm.h" #include From af8626158dbc81a36da5132fe6f21dd5483c1657 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 12:44:54 -0500 Subject: [PATCH 137/240] zm_exception doesn't use anything from zm.h so don't include it --- src/zm_exception.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/zm_exception.h b/src/zm_exception.h index 83d1ecab1..a02653b88 100644 --- a/src/zm_exception.h +++ b/src/zm_exception.h @@ -20,8 +20,6 @@ #ifndef ZM_EXCEPTION_H #define ZM_EXCEPTION_H -#include "zm.h" - #include class Exception From 61759a1f2d4e89598d56982502939ffaf5ad1713 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 12:45:21 -0500 Subject: [PATCH 138/240] older libavcodecs don't have AV_LOG_TRACE AND AV_LOG_MAX_OFFSET --- src/zm_ffmpeg.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 00aee7961..a153dad10 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -43,10 +43,14 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs ) log_level = Logger::DEBUG1; } else if ( level == AV_LOG_DEBUG ) { //48 log_level = Logger::DEBUG2; +#ifdef AV_LOG_TRACE } else if ( level == AV_LOG_TRACE ) { log_level = Logger::DEBUG8; +#endif +#ifdef AV_LOG_MAX_OFFSET } else if ( level == AV_LOG_MAX_OFFSET ) { log_level = Logger::DEBUG9; +#endif } else { Error("Unknown log level %d", level); } From 4d4666f5e03fc1c380444f7219ef7a1e8a827a1e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 12:45:41 -0500 Subject: [PATCH 139/240] add a mutex in logging functions so that multiple threads can log at the same time --- src/zm_logger.cpp | 2 ++ src/zm_logger.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index 9740a100f..c34f6ba41 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -444,6 +444,7 @@ void Logger::closeSyslog() { void Logger::logPrint( bool hex, const char * const filepath, const int line, const int level, const char *fstring, ... ) { if ( level > mEffectiveLevel ) return; + log_mutex.lock(); char timeString[64]; char logString[8192]; va_list argPtr; @@ -579,6 +580,7 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co abort(); exit(-1); } + log_mutex.unlock(); } diff --git a/src/zm_logger.h b/src/zm_logger.h index 8e2ab6c9d..f65c5ec31 100644 --- a/src/zm_logger.h +++ b/src/zm_logger.h @@ -30,6 +30,8 @@ #endif // HAVE_SYS_SYSCALL_H #include +#include "zm_thread.h" + class Logger { public: enum { @@ -82,6 +84,8 @@ private: static bool smInitialised; static Logger *smInstance; + RecursiveMutex log_mutex; + static StringMap smCodes; static IntMap smSyslogPriorities; From 522ecaddd890796b8a384bf5b484e471bd3c27d4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 12:46:10 -0500 Subject: [PATCH 140/240] remove extra include unistd.h and we have to pre-define RecursiveMutex because we use it in zm_logger. --- src/zm_thread.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/zm_thread.h b/src/zm_thread.h index 0c41a93a5..8cdfb892c 100644 --- a/src/zm_thread.h +++ b/src/zm_thread.h @@ -20,9 +20,12 @@ #ifndef ZM_THREAD_H #define ZM_THREAD_H +class RecursiveMutex; + + +#include "zm_config.h" #include #include -#include #ifdef HAVE_SYS_SYSCALL_H #include #endif // HAVE_SYS_SYSCALL_H From 1273cb863ca1bef275e9eb677b10b8a9f8d7d0e2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 13:04:46 -0500 Subject: [PATCH 141/240] send logPrint a pre-formatted string --- src/zm_ffmpeg.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index a153dad10..d0bac6464 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -56,7 +56,9 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs ) } if ( log ) { - log->logPrint(false, __FILE__, __LINE__, log_level, fmt, vargs); + char logString[8192]; + vsnprintf(logString, sizeof(logString)-1, fmt, vargs); + log->logPrint(false, __FILE__, __LINE__, log_level, logString); } } From 6128d2a4d98243456a1e10ecf67e500fc64706e5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 23 Nov 2018 15:34:23 -0500 Subject: [PATCH 142/240] fix #2317 by updating the url encoding of a filter to match events for that monitor --- web/skins/classic/views/js/watch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index bab0888c7..bb94c826b 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -501,11 +501,11 @@ function getEventCmdResponse( respObj, respText ) { var cells = row.getElements( 'td' ); - var link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&terms=1&attr1=MonitorId&op1=%3d&val1='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); + var link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); link.set( 'text', event.Id ); link.inject( row.getElement( 'td.colId' ) ); - link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&terms=1&attr1=MonitorId&op1=%3d&val1='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); + link = new Element( 'a', { 'href': '#', 'events': { 'click': createEventPopup.pass( [ event.Id, '&filter[Query][terms][0][attr]=MonitorId&filter[Query][terms][0][op]=%3d&filter[Query][terms][0][val]='+monitorId+'&page=1&popup=1', event.Width, event.Height ] ) } }); link.set( 'text', event.Name ); link.inject( row.getElement( 'td.colName' ) ); From 0b02996a3fbf5e99d76aa6a35cc143003aeb6794 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 23 Nov 2018 17:11:33 -0600 Subject: [PATCH 143/240] Update zoneminder.spec --- distros/redhat/zoneminder.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 3ff68b080..95476037b 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -125,7 +125,7 @@ Requires: perl(Net::FTP) Requires: perl(LWP::Protocol::https) Requires: ca-certificates Requires: zip -%{systemd_requires} +%{?systemd_requires} Requires(post): %{_bindir}/gpasswd Requires(post): %{_bindir}/chown From 94944abd98848159ace8ca397ce3a8988b789d10 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Nov 2018 09:26:51 -0600 Subject: [PATCH 144/240] Fix triggers to sum event counts properly (#2323) * rpm - update README * update triggers to su mevent counts properly * fix merge error * merge content of triggers.sql with 1.32.3 sql update * populate day, week, month summary tables with existing * populate archive summary table with existing * fix typo * remove startime column from query * my machine is possessed --- db/zm_update-1.32.3.sql | 284 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 277 insertions(+), 7 deletions(-) diff --git a/db/zm_update-1.32.3.sql b/db/zm_update-1.32.3.sql index fe38baede..14525cec1 100644 --- a/db/zm_update-1.32.3.sql +++ b/db/zm_update-1.32.3.sql @@ -1,9 +1,279 @@ --- --- This updates a 1.32.2 database to 1.32.3 --- --- --- Add some additional monitor preset values --- +delimiter // +DROP TRIGGER IF EXISTS Events_Hour_delete_trigger// +CREATE TRIGGER Events_Hour_delete_trigger BEFORE DELETE ON Events_Hour +FOR EACH ROW BEGIN + UPDATE Monitors SET + HourEvents = COALESCE(HourEvents,1)-1, + HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) + WHERE Id=OLD.MonitorId; +END; +// -INSERT INTO MonitorPresets VALUES (NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +DROP TRIGGER IF EXISTS Events_Hour_update_trigger// + +CREATE TRIGGER Events_Hour_update_trigger AFTER UPDATE ON Events_Hour +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) WHERE Monitors.Id=OLD.MonitorId; + UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)-COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId; + ELSE + UPDATE Monitors SET HourEventDiskSpace=COALESCE(HourEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId; + END IF; + END IF; + END; +// +DELIMITER ; + +delimiter // +DROP TRIGGER IF EXISTS Events_Day_delete_trigger// +CREATE TRIGGER Events_Day_delete_trigger BEFORE DELETE ON Events_Day +FOR EACH ROW BEGIN + UPDATE Monitors SET + DayEvents = COALESCE(DayEvents,1)-1, + DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) + WHERE Id=OLD.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS Events_Day_update_trigger; +CREATE TRIGGER Events_Day_update_trigger AFTER UPDATE ON Events_Day +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) WHERE Monitors.Id=OLD.MonitorId; + UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId; + ELSE + UPDATE Monitors SET DayEventDiskSpace=COALESCE(DayEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId; + END IF; + END IF; + END; + // + + +DROP TRIGGER IF EXISTS Events_Week_delete_trigger// +CREATE TRIGGER Events_Week_delete_trigger BEFORE DELETE ON Events_Week +FOR EACH ROW BEGIN + UPDATE Monitors SET + WeekEvents = COALESCE(WeekEvents,1)-1, + WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) + WHERE Id=OLD.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS Events_Week_update_trigger; +CREATE TRIGGER Events_Week_update_trigger AFTER UPDATE ON Events_Week +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) WHERE Monitors.Id=OLD.MonitorId; + UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+COALESCE(NEW.DiskSpace,0) WHERE Monitors.Id=NEW.MonitorId; + ELSE + UPDATE Monitors SET WeekEventDiskSpace=COALESCE(WeekEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId; + END IF; + END IF; + END; + // + +DROP TRIGGER IF EXISTS Events_Month_delete_trigger// +CREATE TRIGGER Events_Month_delete_trigger BEFORE DELETE ON Events_Month +FOR EACH ROW BEGIN + UPDATE Monitors SET + MonthEvents = COALESCE(MonthEvents,1)-1, + MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) + WHERE Id=OLD.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS Events_Month_update_trigger; +CREATE TRIGGER Events_Month_update_trigger AFTER UPDATE ON Events_Month +FOR EACH ROW + BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( diff ) THEN + IF ( NEW.MonitorID != OLD.MonitorID ) THEN + UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)-COALESCE(OLD.DiskSpace) WHERE Monitors.Id=OLD.MonitorId; + UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+COALESCE(NEW.DiskSpace) WHERE Monitors.Id=NEW.MonitorId; + ELSE + UPDATE Monitors SET MonthEventDiskSpace=COALESCE(MonthEventDiskSpace,0)+diff WHERE Monitors.Id=NEW.MonitorId; + END IF; + END IF; + END; + // + +drop procedure if exists update_storage_stats// + +drop trigger if exists event_update_trigger// + +CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events +FOR EACH ROW +BEGIN + declare diff BIGINT default 0; + + set diff = COALESCE(NEW.DiskSpace,0) - COALESCE(OLD.DiskSpace,0); + IF ( NEW.StorageId = OLD.StorageID ) THEN + IF ( diff ) THEN + UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + diff WHERE Id = OLD.StorageId; + END IF; + ELSE + IF ( NEW.DiskSpace ) THEN + UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) + NEW.DiskSpace WHERE Id = NEW.StorageId; + END IF; + IF ( OLD.DiskSpace ) THEN + UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) - OLD.DiskSpace WHERE Id = OLD.StorageId; + END IF; + END IF; + + UPDATE Events_Hour SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Day SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Week SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Month SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + + IF ( NEW.Archived != OLD.Archived ) THEN + IF ( NEW.Archived ) THEN + INSERT INTO Events_Archived (EventId,MonitorId,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.DiskSpace); + UPDATE Monitors SET ArchivedEvents = COALESCE(ArchivedEvents,0)+1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Id=NEW.MonitorId; + ELSEIF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitors SET ArchivedEvents = COALESCE(ArchivedEvents,0)-1, ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) WHERE Id=OLD.MonitorId; + ELSE + IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN + UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Monitors SET + ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0) + WHERE Id=OLD.MonitorId; + END IF; + END IF; + ELSEIF ( NEW.Archived AND diff ) THEN + UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + END IF; + + IF ( diff ) THEN + UPDATE Monitors SET TotalEventDiskSpace = COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + COALESCE(NEW.DiskSpace,0) WHERE Id=OLD.MonitorId; + END IF; + +END; + +// + +delimiter ; + +DROP TRIGGER IF EXISTS event_insert_trigger; + +delimiter // +/* The assumption is that when an Event is inserted, it has no size yet, so don't bother updating the DiskSpace, just the count. + * The DiskSpace will get update in the Event Update Trigger + */ +CREATE TRIGGER event_insert_trigger AFTER INSERT ON Events +FOR EACH ROW + BEGIN + + INSERT INTO Events_Hour (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Day (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Week (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Month (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + UPDATE Monitors SET + HourEvents = COALESCE(HourEvents,0)+1, + DayEvents = COALESCE(DayEvents,0)+1, + WeekEvents = COALESCE(WeekEvents,0)+1, + MonthEvents = COALESCE(MonthEvents,0)+1, + TotalEvents = COALESCE(TotalEvents,0)+1 + WHERE Id=NEW.MonitorId; +END; +// + +DROP TRIGGER IF EXISTS event_delete_trigger// + +CREATE TRIGGER event_delete_trigger BEFORE DELETE ON Events +FOR EACH ROW +BEGIN + IF ( OLD.DiskSpace ) THEN + UPDATE Storage SET DiskSpace = COALESCE(DiskSpace,0) - CAST(OLD.DiskSpace AS SIGNED) WHERE Id = OLD.StorageId; + END IF; + DELETE FROM Events_Hour WHERE EventId=OLD.Id; + DELETE FROM Events_Day WHERE EventId=OLD.Id; + DELETE FROM Events_Week WHERE EventId=OLD.Id; + DELETE FROM Events_Month WHERE EventId=OLD.Id; + IF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitors SET + ArchivedEvents = COALESCE(ArchivedEvents,1) - 1, + ArchivedEventDiskSpace = COALESCE(ArchivedEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0), + TotalEvents = COALESCE(TotalEvents,1) - 1, + TotalEventDiskSpace = COALESCE(TotalEventDiskSpace,0) - COALESCE(OLD.DiskSpace,0) + WHERE Id=OLD.MonitorId; + ELSE + UPDATE Monitors SET + TotalEvents = COALESCE(TotalEvents,1)-1, + TotalEventDiskSpace=COALESCE(TotalEventDiskSpace,0)-COALESCE(OLD.DiskSpace,0) + WHERE Id=OLD.MonitorId; + END IF; +END; + +// + +DROP TRIGGER IF EXISTS Zone_Insert_Trigger// +CREATE TRIGGER Zone_Insert_Trigger AFTER INSERT ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Id=NEW.MonitorID; + END +// +DROP TRIGGER IF EXISTS Zone_Delete_Trigger// +CREATE TRIGGER Zone_Delete_Trigger AFTER DELETE ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Id=OLD.MonitorID; + END +// + +DELIMITER ; + +REPLACE INTO Events_Day SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 day); +REPLACE INTO Events_Week SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 week); +REPLACE INTO Events_Month SELECT Id,MonitorId,StartTime,DiskSpace FROM Events WHERE StartTime > DATE_SUB(NOW(), INTERVAL 1 month); +REPLACE INTO Events_Archived SELECT Id,MonitorId,DiskSpace FROM Events WHERE Archived=1; + +UPDATE Monitors INNER JOIN ( + SELECT MonitorId, + COUNT(Id) AS TotalEvents, + SUM(DiskSpace) AS TotalEventDiskSpace, + SUM(IF(Archived,1,0)) AS ArchivedEvents, + SUM(IF(Archived,DiskSpace,0)) AS ArchivedEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace + FROM Events GROUP BY MonitorId + ) AS E ON E.MonitorId=Monitors.Id SET + Monitors.TotalEvents = E.TotalEvents, + Monitors.TotalEventDiskSpace = E.TotalEventDiskSpace, + Monitors.ArchivedEvents = E.ArchivedEvents, + Monitors.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace, + Monitors.HourEvents = E.HourEvents, + Monitors.HourEventDiskSpace = E.HourEventDiskSpace, + Monitors.DayEvents = E.DayEvents, + Monitors.DayEventDiskSpace = E.DayEventDiskSpace, + Monitors.WeekEvents = E.WeekEvents, + Monitors.WeekEventDiskSpace = E.WeekEventDiskSpace, + Monitors.MonthEvents = E.MonthEvents, + Monitors.MonthEventDiskSpace = E.MonthEventDiskSpace; From 8301f5d03999562130a2be1013c0f8ff40143f03 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 25 Nov 2018 15:42:35 -0600 Subject: [PATCH 145/240] add missing sql update text --- db/zm_update-1.32.3.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/db/zm_update-1.32.3.sql b/db/zm_update-1.32.3.sql index 14525cec1..df776cc5e 100644 --- a/db/zm_update-1.32.3.sql +++ b/db/zm_update-1.32.3.sql @@ -1,3 +1,6 @@ +-- +-- This updates a 1.32.2 database to 1.32.3 +-- delimiter // DROP TRIGGER IF EXISTS Events_Hour_delete_trigger// From b3703a5eede0ac451efae60dbb9676fda0aad1bb Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Nov 2018 15:16:10 -0500 Subject: [PATCH 146/240] Check in db a second time for the event. Long running zmaudits can find an event in the fs that was created after we loaded all the db events. --- scripts/zmaudit.pl.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index 7a5017fbd..fdb9d68ff 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -454,6 +454,12 @@ MAIN: while( $loop ) { my $Event = $fs_events->{$fs_event_id}; if ( ! defined( $db_events->{$fs_event_id} ) ) { + # Long running zmaudits can find events that were created after we loaded all db events. + # So do a secondary lookup + if ( ZoneMinder::Event->find_one(Id=>$fs_event_id) ) { + Debug("$$Event{Id} found in secondary lookup."); + next; + } my $age = $Event->age(); if ( $age > $Config{ZM_AUDIT_MIN_AGE} ) { From 17c193391368c4abb5c1322c021b3d9a25a9e9b1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Nov 2018 16:20:15 -0500 Subject: [PATCH 147/240] remove an extra l --- web/includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 53ea7e199..207eba357 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -53,7 +53,7 @@ function CORSHeaders() { preg_match('/^(https?:\/\/)?'.preg_quote($Server->Name(),'/').'/i', $_SERVER['HTTP_ORIGIN']) ) { $valid = true; - Logger::Debug("Setting Access-Controll-Allow-Origin from " . $_SERVER['HTTP_ORIGIN']); + Logger::Debug("Setting Access-Control-Allow-Origin from " . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Headers: x-requested-with,x-request'); break; From 251ccc0ba9db962da102020f179c66785cf3f7da Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Nov 2018 16:20:52 -0500 Subject: [PATCH 148/240] remove extra () --- src/zm_monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 8ff0a0a64..9f2d92102 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -749,7 +749,7 @@ void Monitor::AddPrivacyBitmask( Zone *p_zones[] ) { } Monitor::State Monitor::GetState() const { - return( (State)shared_data->state ); + return (State)shared_data->state; } int Monitor::GetImage( int index, int scale ) { From 8404f0ef648a04f634276dc1eb699f2f37f992ed Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 26 Nov 2018 16:21:32 -0500 Subject: [PATCH 149/240] When forcing an alarm, print out the event id --- src/zmu.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/zmu.cpp b/src/zmu.cpp index dd38cb0c0..af6cb603d 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -463,10 +463,10 @@ int main(int argc, char *argv[]) { } // end if auth if ( mon_id > 0 ) { - fprintf(stderr,"Monitor %d\n", mon_id); + //fprintf(stderr,"Monitor %d\n", mon_id); Monitor *monitor = Monitor::Load(mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY); if ( monitor ) { - fprintf(stderr,"Monitor %d(%s)\n", monitor->Id(), monitor->Name()); + //fprintf(stderr,"Monitor %d(%s)\n", monitor->Id(), monitor->Name()); if ( verbose ) { printf("Monitor %d(%s)\n", monitor->Id(), monitor->Name()); } @@ -479,9 +479,9 @@ int main(int argc, char *argv[]) { bool have_output = false; if ( function & ZMU_STATE ) { Monitor::State state = monitor->GetState(); - if ( verbose ) + if ( verbose ) { printf("Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle")); - else { + } else { if ( have_output ) printf("%c", separator); printf("%d", state); have_output = true; @@ -560,6 +560,11 @@ int main(int argc, char *argv[]) { if ( verbose ) printf( "Forcing alarm on\n" ); monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" ); + while ( monitor->GetState() != Monitor::ALARM ) { + // Wait for monitor to notice. + usleep(1000); + } + printf( "Alarmed event id: %" PRIu64 "\n", monitor->GetLastEventId() ); } if ( function & ZMU_NOALARM ) { if ( verbose ) From f8b2ff5c77412806cf62665fcc15e9a95bf76af3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 27 Nov 2018 17:35:25 -0500 Subject: [PATCH 150/240] rework from Url() to PathToIndex(), PathToZMS(), UrlToIndex() and UrlToZMS() --- db/zm_create.sql.in | 3 ++- db/zm_update-1.32.3.sql | 30 +++++++++++++++-------- web/includes/Server.php | 26 ++++++++++++++++---- web/skins/classic/views/js/montage.js.php | 2 +- web/skins/classic/views/js/watch.js.php | 2 +- web/skins/classic/views/js/zone.js.php | 2 +- web/skins/classic/views/js/zones.js.php | 2 +- web/skins/classic/views/options.php | 4 +++ web/skins/classic/views/server.php | 11 ++++++--- 9 files changed, 59 insertions(+), 23 deletions(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index b2824b075..240e8f345 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -559,7 +559,8 @@ CREATE TABLE `Servers` ( `Protocol` TEXT, `Hostname` TEXT, `Port` INTEGER UNSIGNED, - `PathPrefix` TEXT, + `PathToIndex` TEXT, + `PathToZMS` TEXT, `Name` varchar(64) NOT NULL default '', `State_Id` int(10) unsigned, `Status` enum('Unknown','NotRunning','Running') NOT NULL default 'Unknown', diff --git a/db/zm_update-1.32.3.sql b/db/zm_update-1.32.3.sql index 68d617824..17bb3c3ab 100644 --- a/db/zm_update-1.32.3.sql +++ b/db/zm_update-1.32.3.sql @@ -2,12 +2,6 @@ -- This updates a 1.32.2 database to 1.32.3 -- --- --- Add some additional monitor preset values --- - -INSERT INTO MonitorPresets VALUES (NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); - -- -- Add Protocol column to Storage -- @@ -25,16 +19,32 @@ PREPARE stmt FROM @s; EXECUTE stmt; -- --- Add Prefix column to Storage +-- Add PathToIndex column to Storage -- SET @s = (SELECT IF( (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() AND table_name = 'Servers' - AND column_name = 'PathPrefix' + AND column_name = 'PathToIndex' ) > 0, -"SELECT 'Column PathPrefix already exists in Servers'", -"ALTER TABLE Servers ADD `PathPrefix` TEXT AFTER `Hostname`" +"SELECT 'Column PathToIndex already exists in Servers'", +"ALTER TABLE Servers ADD `PathToIndex` TEXT AFTER `Hostname`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +-- +-- Add PathToZMS column to Storage +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Servers' + AND column_name = 'PathToZMS' + ) > 0, +"SELECT 'Column PathToZMS already exists in Servers'", +"ALTER TABLE Servers ADD `PathToZMS` TEXT AFTER `PathToIndex`" )); PREPARE stmt FROM @s; diff --git a/web/includes/Server.php b/web/includes/Server.php index 7d0b5f436..4c7dc79b2 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -72,6 +72,19 @@ class Server { return $_SERVER['SERVER_PORT']; } + public function PathToZMS( $new = null ) { + if ( $new != null ) + $this{'PathToZMS'} = $new; + if ( $this->Id() and $this->{'PathToZMS'} ) { + return $this->{'PathToZMS'}; + } else { + return ZM_PATH_ZMS; + } + } + public function UrlToZMS( ) { + return $this->Url().$this->PathToZMS(); + } + public function Url( $port = null ) { $url = $this->Protocol().'://'; if ( $this->Id() ) { @@ -84,20 +97,23 @@ class Server { } else { $url .= ':'.$this->Port(); } - $url .= $this->PathPrefix(); return $url; } - public function PathPrefix( $new = null ) { + public function PathToIndex( $new = null ) { if ( $new != null ) - $this->{'PathPrefix'} = $new; + $this->{'PathToIndex'} = $new; - if ( isset($this->{'PathPrefix'}) and $this->{'PathPrefix'} ) { - return $this->{'PathPrefix'}; + if ( isset($this->{'PathToIndex'}) and $this->{'PathToIndex'} ) { + return $this->{'PathToIndex'}; } return $_SERVER['PHP_SELF']; } + public function UrlToIndex( ) { + return $this->Url().$this->PathToIndex(); + } + public function __call($fn, array $args){ if ( count($args) ) { $this->{$fn} = $args[0]; diff --git a/web/skins/classic/views/js/montage.js.php b/web/skins/classic/views/js/montage.js.php index 183f17648..fe298ab10 100644 --- a/web/skins/classic/views/js/montage.js.php +++ b/web/skins/classic/views/js/montage.js.php @@ -35,7 +35,7 @@ monitorData[monitorData.length] = { 'connKey': connKey() ?>, 'width': Width() ?>, 'height':Height() ?>, - 'url': 'Url() ?>', + 'url': 'UrlToIndex() ?>', 'onclick': function(){createPopup( '?view=watch&mid=Id() ?>', 'zmWatchId() ?>', 'watch', Width(), $monitor->PopupScale() ); ?>, Height(), $monitor->PopupScale() ); ?> );}, 'type': 'Type() ?>', 'refresh': 'Refresh() ?>' diff --git a/web/skins/classic/views/js/watch.js.php b/web/skins/classic/views/js/watch.js.php index 51c1801e8..15a43a6ce 100644 --- a/web/skins/classic/views/js/watch.js.php +++ b/web/skins/classic/views/js/watch.js.php @@ -48,7 +48,7 @@ var maxDisplayEvents = ; var monitorId = Id() ?>; var monitorWidth = Width() ?>; var monitorHeight = Height() ?>; -var monitorUrl = 'Url(); ?>'; +var monitorUrl = 'UrlToIndex(); ?>'; var monitorType = 'Type() ) ?>'; var monitorRefresh = 'Refresh() ) ?>'; diff --git a/web/skins/classic/views/js/zone.js.php b/web/skins/classic/views/js/zone.js.php index 434fec679..069a0de54 100644 --- a/web/skins/classic/views/js/zone.js.php +++ b/web/skins/classic/views/js/zone.js.php @@ -101,7 +101,7 @@ var streamMode = ""; var connKey = ''; var monitorId = Id() ?>; -var monitorUrl = 'Url() ) ?>'; +var monitorUrl = 'UrlToIndex() ) ?>'; var streamSrc = ""; diff --git a/web/skins/classic/views/js/zones.js.php b/web/skins/classic/views/js/zones.js.php index d7144d18a..6bd9c402c 100644 --- a/web/skins/classic/views/js/zones.js.php +++ b/web/skins/classic/views/js/zones.js.php @@ -1,4 +1,4 @@ var connKey = ''; -var monitorUrl = 'Url() ) ?>'; +var monitorUrl = 'UrlToIndex() ) ?>'; var CMD_QUIT = ; diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index 32c0bf436..d4757fbdc 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -209,6 +209,8 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI + + @@ -228,6 +230,8 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI Id(), 'zmServer', 'server', validHtmlStr($Server->Name()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($Server->Url()), $canEdit) ?> + Id(), 'zmServer', 'server', validHtmlStr($Server->PathToIndex()), $canEdit) ?> + Id(), 'zmServer', 'server', validHtmlStr($Server->PathToZMS()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($Server->Status()), $canEdit) ?> diff --git a/web/skins/classic/views/server.php b/web/skins/classic/views/server.php index 2a4ebe785..a1a24ae3b 100644 --- a/web/skins/classic/views/server.php +++ b/web/skins/classic/views/server.php @@ -33,7 +33,8 @@ if ( $_REQUEST['id'] ) { $newServer['Name'] = translate('NewServer'); $newServer['Protocol'] = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http'; $newServer['Hostname'] = ''; - $newServer['PathPrefix'] = '/zm'; + $newServer['PathToIndex'] = '/zm/index.php'; + $newServer['PathToZMS'] = ZM_PATH_ZMS; $newServer['zmstats'] = ''; $newServer['zmaudit'] = ''; $newServer['zmtrigger'] = ''; @@ -72,8 +73,12 @@ xhtmlHeaders(__FILE__, translate('Server').' - '.$newServer['Name']); - - + + + + + + From 94d8e043ce373ecd3fab0aeca87a26d96b83bd44 Mon Sep 17 00:00:00 2001 From: Elmar Pruesse Date: Tue, 27 Nov 2018 16:25:05 -0700 Subject: [PATCH 151/240] Fix unreadable input text when OS theme dark (#2324) * Update skin.css * Update skin.css --- web/skins/classic/css/base/skin.css | 1 + web/skins/classic/css/classic/skin.css | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/css/base/skin.css b/web/skins/classic/css/base/skin.css index 3fdd5a12f..47e7864c2 100644 --- a/web/skins/classic/css/base/skin.css +++ b/web/skins/classic/css/base/skin.css @@ -150,6 +150,7 @@ input,textarea,select,button,.btn-primary { font-weight: 400; font-size: 100%; color: #333333; + background-color: #f8f8f8; text-align: left; border-radius:4px; } diff --git a/web/skins/classic/css/classic/skin.css b/web/skins/classic/css/classic/skin.css index ecd9f3949..b90412093 100644 --- a/web/skins/classic/css/classic/skin.css +++ b/web/skins/classic/css/classic/skin.css @@ -85,7 +85,8 @@ input,textarea,select,button { border: 1px #7f7fb2 solid; font-family: inherit; font-size: 100%; - color: #333333; + color: #333333; + background-color: #eeeeee; } input[type=text], input[type=password], textarea { From 9c1578e14ebfda4a0e0d75fb04fe44f67890ad62 Mon Sep 17 00:00:00 2001 From: Elmar Pruesse Date: Tue, 27 Nov 2018 19:49:58 -0700 Subject: [PATCH 152/240] Add description for Stream Replay Image Buffer (#2325) * Add description for Stream Replay Image Buffer I hope this is even correct. * Update definemonitor.rst --- docs/userguide/definemonitor.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/userguide/definemonitor.rst b/docs/userguide/definemonitor.rst index bcd195570..396f98382 100644 --- a/docs/userguide/definemonitor.rst +++ b/docs/userguide/definemonitor.rst @@ -205,7 +205,8 @@ Warm-up Frames Pre/Post Event Image Buffer These options determine how many frames from before and after an event should be preserved with it. This allows you to view what happened immediately prior and subsequent to the event. A value of 10 for both of these will get you started but if you get a lot of short events and would prefer them to run together to form fewer longer ones then increase the Post Event buffer size. The pre-event buffer is a true buffer and should not really exceed half the ring buffer size. However the post-event buffer is just a count that is applied to captured frames and so can be managed more flexibly. You should also bear in mind the frame rate of the camera when choosing these values. For instance a network camera capturing at 1FPS will give you 10 seconds before and after each event if you chose 10 here. This may well be too much and pad out events more than necessary. However a fast video card may capture at 25FPS and you will want to ensure that this setting enables you to view a reasonable time frame pre and post event. Stream Replay Image Buffer - This option ... + The number of frames buffered to allow pausing and rewinding of the stream when live viewing a monitor. A value of 0 disables the feature. + Frames are buffered to ZM_PATH_SWAP. If this path points to a physical drive, a lot of IO will be caused during live view / montage. If you experience high system load in those situations, either disable the feature or use a RAM drive for ZM_PATH_SWAP. Alarm Frame Count This option allows you to specify how many consecutive alarm frames must occur before an alarm event is generated. The usual, and default, value is 1 which implies that any alarm frame will cause or participate in an event. You can enter any value up to 16 here to eliminate bogus events caused perhaps by screen flickers or other transients. Values over 3 or 4 are unlikely to be useful however. Please note that if you have statistics recording enabled then currently statistics are not recorded for the first ‘Alarm Frame Count’-1 frames of an event. So if you set this value to 5 then the first 4 frames will be missing statistics whereas the more usual value of 1 will ensure that all alarm frames have statistics recorded. From 2b48b09ef58a3cd6429ede6f5c8a4fddd6cc8f81 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Nov 2018 09:53:35 -0500 Subject: [PATCH 153/240] Add entries for PathToIndex and PathToZMS --- web/lang/en_gb.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index 01a458b21..24950fa8e 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -584,7 +584,8 @@ $SLANG = array( 'Parameter' => 'Parameter', 'Password' => 'Password', 'PasswordsDifferent' => 'The new and confirm passwords are different', - 'PathPrefix' => 'Path Prefix', + 'PathToIndex' => 'Path To Index', + 'PathToZMS' => 'Path To ZMS', 'Paths' => 'Paths', 'Pause' => 'Pause', 'PhoneBW' => 'Phone B/W', From cd13dda2948274f7a22e02929bf30c9b32bc17f1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Nov 2018 09:54:22 -0500 Subject: [PATCH 154/240] fix use of instead of --- 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 d4757fbdc..d394f32a1 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -232,7 +232,7 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI Id(), 'zmServer', 'server', validHtmlStr($Server->Url()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($Server->PathToIndex()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($Server->PathToZMS()), $canEdit) ?> - + Id(), 'zmServer', 'server', validHtmlStr($Server->Status()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($monitor_counts[$Server->Id()]), $canEdit) ?> From a89dd83565c264dd3b5eda50d0118141ea87567a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Nov 2018 09:55:34 -0500 Subject: [PATCH 155/240] Update to use object instead of db row --- web/skins/classic/views/server.php | 49 ++++++++++++------------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/web/skins/classic/views/server.php b/web/skins/classic/views/server.php index a1a24ae3b..6b8f41893 100644 --- a/web/skins/classic/views/server.php +++ b/web/skins/classic/views/server.php @@ -23,34 +23,23 @@ if ( !canEdit('System') ) { return; } -if ( $_REQUEST['id'] ) { - if ( !($newServer = dbFetchOne('SELECT * FROM Servers WHERE Id = ?', NULL, ARRAY($_REQUEST['id'])) ) ) { - $view = 'error'; - return; - } -} else { - $newServer = array(); - $newServer['Name'] = translate('NewServer'); - $newServer['Protocol'] = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http'; - $newServer['Hostname'] = ''; - $newServer['PathToIndex'] = '/zm/index.php'; - $newServer['PathToZMS'] = ZM_PATH_ZMS; - $newServer['zmstats'] = ''; - $newServer['zmaudit'] = ''; - $newServer['zmtrigger'] = ''; +$Server = new Server($_REQUEST['id']); +if ( $_REQUEST['id'] and ! $Server->Id() ) { + $view = 'error'; + return; } $focusWindow = true; -xhtmlHeaders(__FILE__, translate('Server').' - '.$newServer['Name']); +xhtmlHeaders(__FILE__, translate('Server').' - '.$Server->Name()); ?>
-
+ @@ -58,47 +47,47 @@ xhtmlHeaders(__FILE__, translate('Server').' - '.$newServer['Name']); - + - + - + - + - + - + - /> Yes - /> No + zmstats() ? ' checked="checked"' : '' ?>/> Yes + zmstats() ? '' : ' checked="checked"' ?>/> No - /> Yes - /> No + zmaudit() ? ' checked="checked"' : '' ?>/> Yes + zmaudit() ? '' : ' checked="checked"' ?>/> No - /> Yes - /> No + zmtrigger() ? ' checked="checked"' : '' ?>/> Yes + zmtrigger() ? '' : ' checked="checked"' ?>/> No From 81f345a9cd6066474ed6b1f59c77a4228ad9acb9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 28 Nov 2018 10:08:27 -0500 Subject: [PATCH 156/240] Add dh-systemd and dh-apache2 to build depends --- distros/ubuntu1604/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index d4fe74e79..e487d17b6 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -3,7 +3,7 @@ Section: net Priority: optional Maintainer: Dmitry Smirnov Uploaders: Vagrant Cascadian -Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree +Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apache2-dev, dh-linktree, dh-systemd, dh-apache2 ,cmake ,libx264-dev, libmp4v2-dev ,libavdevice-dev (>= 6:10~) From e6b8a7bc66d7b18ea7ce87dfef9833250aab6f98 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Thu, 29 Nov 2018 09:21:10 -0500 Subject: [PATCH 157/240] resolves #2327 --- web/api/app/Controller/HostController.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php index 017bce798..d4e19fd77 100644 --- a/web/api/app/Controller/HostController.php +++ b/web/api/app/Controller/HostController.php @@ -65,18 +65,17 @@ class HostController extends AppController { $isZmAuth = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH')))['Config']['Value']; if ( $isZmAuth ) { + // In future, we may want to completely move to AUTH_HASH_LOGINS and return &auth= for all cases require_once "../../../includes/auth.php"; # in the event we directly call getCredentials.json $this->Session->read('user'); # this is needed for command line/curl to recognize a session $zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value']; if ( $zmAuthRelay == 'hashed' ) { $zmAuthHashIps = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value']; $credentials = 'auth='.generateAuthHash($zmAuthHashIps); - } else if ( $zmAuthRelay == 'plain' ) { + } else { // user will need to append the store password here $credentials = 'user='.$this->Session->read('user.Username').'&pass='; $appendPassword = 1; - } else if ( $zmAuthRelay == 'none' ) { - $credentials = 'user='.$this->Session->read('user.Username'); } } return array($credentials, $appendPassword); From 605397b565433a3c68355565406cb29fcf9c029a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Nov 2018 09:43:21 -0500 Subject: [PATCH 158/240] Fix rate resetting by storing it in a cookie and using that on initial event load. Fixes #2319 --- web/skins/classic/views/event.php | 2 ++ web/skins/classic/views/js/event.js | 17 ++++++++++++++--- web/skins/classic/views/js/event.js.php | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index 12fd62c20..bc8fa324e 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -38,6 +38,8 @@ $Monitor = $Event->Monitor(); if (isset($_REQUEST['rate'])) { $rate = validInt($_REQUEST['rate']); +} else if ( isset($_COOKIE['zmEventRate']) ) { + $rate = $_COOKIE['zmEventRate']; } else { $rate = reScale(RATE_BASE, $Monitor->DefaultRate(), ZM_WEB_DEFAULT_RATE); } diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 7f46936a9..9981b1458 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -235,6 +235,7 @@ function getCmdResponse( respObj, respText ) { streamPause( ); } else { $j('#rateValue').html(streamStatus.rate); + Cookie.write('zmEventRate', streamStatus.rate*100, {duration: 10*365}); streamPlay( ); } $j('#progressValue').html(secsToTime(parseInt(streamStatus.progress))); @@ -303,8 +304,10 @@ function playClicked( ) { } function vjsPlay() { //catches if we change mode programatically - stopFastRev(); + if ( intervalRewind ) + stopFastRev(); $j('#rateValue').html(vid.playbackRate()); + Cookie.write('zmEventRate', vid.playbackRate(), {duration: 10*365}); streamPlay(); } @@ -331,6 +334,7 @@ function streamFastFwd( action ) { if ( rates.indexOf(vid.playbackRate()*100)-1 == -1 ) setButtonState($('fastFwdBtn'), 'unavail'); $j('#rateValue').html(vid.playbackRate()); + Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365}); } else { streamReq.send(streamParms+"&command="+CMD_FASTFWD); } @@ -359,6 +363,7 @@ function streamSlowRev( action ) { function stopFastRev() { clearInterval(intervalRewind); vid.playbackRate(1); + Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365}); revSpeed = .5; } @@ -369,13 +374,14 @@ function streamFastRev( action ) { setButtonState( $('slowFwdBtn'), 'unavail' ); setButtonState( $('slowRevBtn'), 'unavail' ); setButtonState( $('fastRevBtn'), 'active' ); - if ( vid ) { //There is no reverse play with mp4. Set the speed to 0 and manualy set the time back. + if ( vid ) { //There is no reverse play with mp4. Set the speed to 0 and manually set the time back. revSpeed = rates[rates.indexOf(revSpeed*100)-1]/100; if ( rates.indexOf(revSpeed*100) == 0 ) { setButtonState( $('fastRevBtn'), 'unavail' ); } clearInterval(intervalRewind); $j('#rateValue').html(-revSpeed); + Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365}); intervalRewind = setInterval(function() { if (vid.currentTime() <= 0) { clearInterval(intervalRewind); @@ -997,8 +1003,13 @@ function initPage() { vid.on('pause', vjsPause); vid.on('click', function(event){handleClick(event);}); vid.on('timeupdate', function (){$j('#progressValue').html(secsToTime(Math.floor(vid.currentTime())))}); + + if ( rate > 1 ) { + // rate should be 100 = 1x, etc. + vid.playbackRate(rate/100); + } } else { - progressBarNav (); + progressBarNav(); streamCmdTimer = streamQuery.delay( 250 ); if ( canStreamNative ) { var imageFeed = $('imageFeed'); diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php index b1924a752..8783bbe06 100644 --- a/web/skins/classic/views/js/event.js.php +++ b/web/skins/classic/views/js/event.js.php @@ -41,6 +41,7 @@ var filterQuery = ''; var rates = ; +var rate = ''; // really only used when setting up initial playback rate. var scale = ""; var LabelFormat = "LabelFormat())?>"; From 45a9f9158d256f1a601d5ba2c6d630e581e559e5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Nov 2018 10:45:30 -0500 Subject: [PATCH 159/240] spelling mistakes --- docs/faq.rst | 2 +- docs/userguide/definemonitor.rst | 2 +- .../ONVIF/Device/Interfaces/Device/DevicePort.pm | 16 ++++++---------- .../lib/ONVIF/PTZ/Interfaces/PTZ/PTZPort.pm | 2 +- scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in | 2 +- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 7735ff38f..a703fd065 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -311,7 +311,7 @@ There are a number of specific reasons why processor loads can be high either by The main causes are. - * Using a video palette other than greyscale or RGB24. This can cause a relatively minor performace hit, though still significant. Although some cameras and cards require using planar palettes ZM currently doesn't support this format internally and each frame is converted to an RGB representation prior to processing. Unless you have compelling reasons for using YUV or reduced RGB type palettes such as hitting USB transfer limits I would experiment to see if RGB24 or greyscale is quicker. Put your monitors into 'Monitor' mode so that only the capture daemons are running and monitor the process load of these (the 'zmc' processes) using top. Try it with various palettes to see if it makes a difference. + * Using a video palette other than greyscale or RGB24. This can cause a relatively minor performance hit, though still significant. Although some cameras and cards require using planar palettes ZM currently doesn't support this format internally and each frame is converted to an RGB representation prior to processing. Unless you have compelling reasons for using YUV or reduced RGB type palettes such as hitting USB transfer limits I would experiment to see if RGB24 or greyscale is quicker. Put your monitors into 'Monitor' mode so that only the capture daemons are running and monitor the process load of these (the 'zmc' processes) using top. Try it with various palettes to see if it makes a difference. * Big image sizes. A image of 640x480 requires at least four times the processing of a 320x240 image. Experiment with different sizes to see what effect it may have. Sometimes a large image is just two interlaced smaller frames so has no real benefit anyway. This is especially true for analog cameras/cards as image height over 320 (NTSC) or 352 PAL) are invariably interlaced. * Capture frame rates. Unless there's a compelling reason in your case there is often little benefit in running cameras at 25fps when 5-10fps would often get you results just as good. Try changing your monitor settings to limit your cameras to lower frame rates. You can still configure ZM to ignore these limits and capture as fast as possible when motion is detected. * Run function. Obviously running in Record or Mocord modes or in Modect with lots of events generates a lot of DB and file activity and so CPU and load will increase. diff --git a/docs/userguide/definemonitor.rst b/docs/userguide/definemonitor.rst index bcd195570..90bfc9a37 100644 --- a/docs/userguide/definemonitor.rst +++ b/docs/userguide/definemonitor.rst @@ -58,7 +58,7 @@ Maximum FPS Alarm Maximum FPS If you have specified a Maximum FPS it may be that you don’t want this limitation to apply when your monitor is recording motion or other event. This setting allows you to override the Maximum FPS value if this circumstance occurs. As with the Maximum FPS setting leaving this blank implies no limit so if you have set a maximum fps in the previous option then when an alarm occurs this limit would be ignored and ZoneMinder would capture as fast as possible for the duration of the alarm, returning to the limited value after the alarm has concluded. Equally you could set this to the same, or higher (or even lower) value than Maximum FPS for more precise control over the capture rate in the event of an alarm. - **IMPORTANT:** This field is subject to the same limitations as the Maxium FPS field. Ignoring these limitations will produce undesriable results. + **IMPORTANT:** This field is subject to the same limitations as the Maximum FPS field. Ignoring these limitations will produce undesriable results. Reference Image Blend %ge Each analysed image in ZoneMinder is a composite of previous images and is formed by applying the current image as a certain percentage of the previous reference image. Thus, if we entered the value of 10 here, each image’s part in the reference image will diminish by a factor of 0.9 each time round. So a typical reference image will be 10% the previous image, 9% the one before that and then 8.1%, 7.2%, 6.5% and so on of the rest of the way. An image will effectively vanish around 25 images later than when it was added. This blend value is what is specified here and if higher will make slower progressing events less detectable as the reference image would change more quickly. Similarly events will be deemed to be over much sooner as the reference image adapts to the new images more quickly. In signal processing terms the higher this value the steeper the event attack and decay of the signal. It depends on your particular requirements what the appropriate value would be for you but start with 10 here and adjust it (usually down) later if necessary. diff --git a/onvif/proxy/lib/ONVIF/Device/Interfaces/Device/DevicePort.pm b/onvif/proxy/lib/ONVIF/Device/Interfaces/Device/DevicePort.pm index 35f259f31..c3c488ba1 100644 --- a/onvif/proxy/lib/ONVIF/Device/Interfaces/Device/DevicePort.pm +++ b/onvif/proxy/lib/ONVIF/Device/Interfaces/Device/DevicePort.pm @@ -25,15 +25,13 @@ sub GetServices { soap_action => 'http://www.onvif.org/ver10/device/wsdl/GetServices', style => 'document', body => { - - - 'use' => 'literal', + use => 'literal', namespace => 'http://schemas.xmlsoap.org/wsdl/soap/', encodingStyle => '', parts => [qw( ONVIF::Device::Elements::GetServices )], }, header => { - + }, headerfault => { @@ -50,9 +48,7 @@ sub GetServiceCapabilities { soap_action => 'http://www.onvif.org/ver10/device/wsdl/GetServiceCapabilities', style => 'document', body => { - - - 'use' => 'literal', + use => 'literal', namespace => 'http://schemas.xmlsoap.org/wsdl/soap/', encodingStyle => '', parts => [qw( ONVIF::Device::Elements::GetServiceCapabilities )], @@ -3059,7 +3055,7 @@ Returns a L object. @@ -3069,7 +3065,7 @@ Returns a L object. @@ -3085,7 +3081,7 @@ Returns a L object. diff --git a/onvif/proxy/lib/ONVIF/PTZ/Interfaces/PTZ/PTZPort.pm b/onvif/proxy/lib/ONVIF/PTZ/Interfaces/PTZ/PTZPort.pm index 8d42d439e..d1c5faa29 100644 --- a/onvif/proxy/lib/ONVIF/PTZ/Interfaces/PTZ/PTZPort.pm +++ b/onvif/proxy/lib/ONVIF/PTZ/Interfaces/PTZ/PTZPort.pm @@ -830,7 +830,7 @@ Returns a L object. diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in index 7c5292720..205494791 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -812,7 +812,7 @@ shared_data The general mapped memory section size The size, in bytes, of this section valid Flag indicating whether this section has been initialised active Flag indicating whether this monitor is active (enabled/disabled) -signal Flag indicating whether this monitor is reciving a valid signal +signal Flag indicating whether this monitor is receiving a valid signal state The current monitor state, see the STATE constants below last_write_index The last index, in the image buffer, that an image has been saved to last_read_index The last index, in the image buffer, that an image has been analysed from From 5496f6afaca50af53ceb1325a15b433aba8a390d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Nov 2018 10:48:16 -0500 Subject: [PATCH 160/240] add cosmic and disco to ubuntu builds --- utils/do_debian_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh index 71f1ec460..a87c03379 100755 --- a/utils/do_debian_package.sh +++ b/utils/do_debian_package.sh @@ -76,7 +76,7 @@ fi; if [ "$DISTROS" == "" ]; then if [ "$RELEASE" != "" ]; then - DISTROS="xenial,bionic,trusty" + DISTROS="xenial,bionic,cosmic,disco,trusty" else DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`; fi; From 79f804e94b67ef6515a126cd88cf1a87cb517ae0 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 29 Nov 2018 10:43:22 -0600 Subject: [PATCH 161/240] update rpm README --- distros/redhat/readme/README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/distros/redhat/readme/README b/distros/redhat/readme/README index 065628321..b26a4e2f8 100644 --- a/distros/redhat/readme/README +++ b/distros/redhat/readme/README @@ -7,7 +7,7 @@ What's New 2. The contents of the ZoneMinder Apache config file have changed. In addition, this ZoneMinder package now requires you to manually symlink the ZoneMinder Apache config file. See new install step 6 and upgrade step 3 - below for details. + in the appropriate README for details. 3. This package has been split into sub-packages to allow compatibility with other web servers. Here is a breakdown of the available packages: @@ -19,9 +19,9 @@ What's New zoneminder-nginx - Files needed for compatibility with the Nginx web server You can switch between different subpackages with dnf/yum. Be advised that, - if you modified any of the default config files supplied by the package, - rpm may not update the config file to the proper version. This is by design. - To avoid this issue, use drop-in files instead. + switching between httpd <-> nginx may not be perfect. Several files and + folders need to change ownership. The package attempts to do this, but + manual intervention will still likely be needed. 4. If you have installed ZoneMinder from the FedBerry repositories, this build of ZoneMinder has support for Raspberry Pi hardware acceleration when using From 5e0d742e2629eb36e1d759a055eacada1c4f8347 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Nov 2018 14:04:35 -0500 Subject: [PATCH 162/240] Use history.go(-1) which works on safari --- web/skins/classic/views/watch.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index 72c266d29..e6759dc39 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -75,7 +75,7 @@ if ( canView('Control') && $monitor->Type() == 'Local' ) { ?>
:
-
+
$scale) ); ?>
From 1c17f334d31ce444d96d257a396d3499d75a7585 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Nov 2018 14:26:30 -0500 Subject: [PATCH 163/240] fix missing bits. Implement UrlToIndex in Monitor and fix use of Url(). Implement PathToApi as well --- db/zm_create.sql.in | 1 + db/zm_update-1.32.3.sql | 16 ++++++++++++++++ web/includes/Event.php | 11 +++++------ web/includes/Monitor.php | 8 +++----- web/includes/Server.php | 17 ++++++++++++++++- web/lang/en_gb.php | 1 + web/skins/classic/views/options.php | 2 ++ web/skins/classic/views/server.php | 4 ++++ 8 files changed, 48 insertions(+), 12 deletions(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 240e8f345..e9f0ca9ab 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -561,6 +561,7 @@ CREATE TABLE `Servers` ( `Port` INTEGER UNSIGNED, `PathToIndex` TEXT, `PathToZMS` TEXT, + `PathToApi` TEXT, `Name` varchar(64) NOT NULL default '', `State_Id` int(10) unsigned, `Status` enum('Unknown','NotRunning','Running') NOT NULL default 'Unknown', diff --git a/db/zm_update-1.32.3.sql b/db/zm_update-1.32.3.sql index a5f6eca1b..6c3e2c47f 100644 --- a/db/zm_update-1.32.3.sql +++ b/db/zm_update-1.32.3.sql @@ -329,6 +329,22 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; +-- +-- Add PathToApi column to Storage +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Servers' + AND column_name = 'PathToApi' + ) > 0, +"SELECT 'Column PathToApi already exists in Servers'", +"ALTER TABLE Servers ADD `PathToApi` TEXT AFTER `PathToZMS`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + -- -- Add Port column to Storage -- diff --git a/web/includes/Event.php b/web/includes/Event.php index 2046f5ddf..27d9ae015 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -221,11 +221,11 @@ class Event { null); if ( $this->{'DefaultVideo'} and $args['mode'] != 'jpeg' ) { - $streamSrc .= ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php'; + $streamSrc .= $Server->PathToIndex(); $args['eid'] = $this->{'Id'}; $args['view'] = 'view_video'; } else { - $streamSrc .= ZM_PATH_ZMS; + $streamSrc .= $Server->PathToZMS(); $args['source'] = 'event'; $args['event'] = $this->{'Id'}; @@ -340,12 +340,11 @@ class Event { } else { $Server = new Server(); } - $streamSrc .= $Server->Url( + $streamSrc .= $Server->UrlToIndex( ZM_MIN_STREAMING_PORT ? ZM_MIN_STREAMING_PORT+$this->{'MonitorId'} : null); - $streamSrc .= ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php'; $args['eid'] = $this->{'Id'}; $args['fid'] = 'snapshot'; $args['view'] = 'image'; @@ -573,7 +572,7 @@ class Event { $Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server(); if ( $Server->Id() != ZM_SERVER_ID ) { - $url = $Server->Url() . '/zm/api/events/'.$this->{'Id'}.'.json'; + $url = $Server->UrlToApi() . '/events/'.$this->{'Id'}.'.json'; if ( ZM_OPT_USE_AUTH ) { if ( ZM_AUTH_RELAY == 'hashed' ) { $url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS ); @@ -617,7 +616,7 @@ class Event { $Server = $Storage->ServerId() ? $Storage->Server() : $this->Monitor()->Server(); if ( $Server->Id() != ZM_SERVER_ID ) { - $url = $Server->Url() . '/zm/api/events/'.$this->{'Id'}.'.json'; + $url = $Server->UrlToApi() . '/events/'.$this->{'Id'}.'.json'; if ( ZM_OPT_USE_AUTH ) { if ( ZM_AUTH_RELAY == 'hashed' ) { $url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS ); diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 500ae171f..c1a6a47df 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -282,13 +282,11 @@ private $control_fields = array( public function getStreamSrc($args, $querySep='&') { - $streamSrc = $this->Server()->Url( + $streamSrc = $this->Server()->UrlToZMS( ZM_MIN_STREAMING_PORT ? ZM_MIN_STREAMING_PORT+$this->{'Id'} : null); - $streamSrc .= ZM_PATH_ZMS; - $args['monitor'] = $this->{'Id'}; if ( ZM_OPT_USE_AUTH ) { @@ -620,8 +618,8 @@ private $control_fields = array( return $source; } // end function Source - public function Url() { - return $this->Server()->Url( ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null ); + public function UrlToIndex() { + return $this->Server()->UrlToIndex(ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : null); } } // end class Monitor diff --git a/web/includes/Server.php b/web/includes/Server.php index 4c7dc79b2..069e5830c 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -10,7 +10,9 @@ class Server { 'Protocol' => '', 'Hostname' => '', 'Port' => null, - 'PathPrefix' => '/zm', + 'PathToIndex' => '/zm', + 'PathToZMS' => ZM_PATH_ZMS, + 'PathToApi' => '/zm/api', 'zmaudit' => 1, 'zmstats' => 1, 'zmtrigger' => 0, @@ -81,6 +83,7 @@ class Server { return ZM_PATH_ZMS; } } + public function UrlToZMS( ) { return $this->Url().$this->PathToZMS(); } @@ -113,6 +116,18 @@ class Server { public function UrlToIndex( ) { return $this->Url().$this->PathToIndex(); } + public function UrlToApi( ) { + return $this->Url().$this->PathToApi(); + } + public function PathToApi( $new = null ) { + if ( $new != null ) + $this->{'PathToApi'} = $new; + + if ( isset($this->{'PathToApi'}) and $this->{'PathToApi'} ) { + return $this->{'PathToApi'}; + } + return '/zm/api'; + } public function __call($fn, array $args){ if ( count($args) ) { diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index 24950fa8e..721a86253 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -586,6 +586,7 @@ $SLANG = array( 'PasswordsDifferent' => 'The new and confirm passwords are different', 'PathToIndex' => 'Path To Index', 'PathToZMS' => 'Path To ZMS', + 'PathToApi' => 'Path To Api', 'Paths' => 'Paths', 'Pause' => 'Pause', 'PhoneBW' => 'Phone B/W', diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php index d394f32a1..1b907dfc1 100644 --- a/web/skins/classic/views/options.php +++ b/web/skins/classic/views/options.php @@ -211,6 +211,7 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI + @@ -232,6 +233,7 @@ foreach ( array_map('basename', glob('skins/'.$current_skin.'/css/*',GLOB_ONLYDI Id(), 'zmServer', 'server', validHtmlStr($Server->Url()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($Server->PathToIndex()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($Server->PathToZMS()), $canEdit) ?> + Id(), 'zmServer', 'server', validHtmlStr($Server->PathToApi()), $canEdit) ?> Id(), 'zmServer', 'server', validHtmlStr($Server->Status()), $canEdit) ?> diff --git a/web/skins/classic/views/server.php b/web/skins/classic/views/server.php index 6b8f41893..42dd5fc6f 100644 --- a/web/skins/classic/views/server.php +++ b/web/skins/classic/views/server.php @@ -69,6 +69,10 @@ xhtmlHeaders(__FILE__, translate('Server').' - '.$Server->Name()); + + + + From 3bd5774ea170706e398d447c9693295b37184997 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 29 Nov 2018 15:53:19 -0500 Subject: [PATCH 164/240] Default to PathToIndex should have the index.php in it --- web/includes/Server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/Server.php b/web/includes/Server.php index 069e5830c..06219a1f5 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -10,7 +10,7 @@ class Server { 'Protocol' => '', 'Hostname' => '', 'Port' => null, - 'PathToIndex' => '/zm', + 'PathToIndex' => '/zm/index.php', 'PathToZMS' => ZM_PATH_ZMS, 'PathToApi' => '/zm/api', 'zmaudit' => 1, From bfff07bb3e1977fd3662e10c2d9440153560116f Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 30 Nov 2018 08:53:58 -0600 Subject: [PATCH 165/240] rpm packaging - takes too long to set perms on events --- distros/redhat/zoneminder.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 95476037b..59fd3dc81 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -253,7 +253,6 @@ echo -e "\nThe README file is located here: %{_pkgdocdir}-common/README\n" # For the case of changing from nginx <-> httpd, files in these folders must change ownership if they exist %{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/php/session/* >/dev/null 2>&1 || : %{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_localstatedir}/log/zoneminder/* >/dev/null 2>&1 || : -%{_bindir}/chown -R %{zmuid_final}:%{zmgid_final} %{_sharedstatedir}/zoneminder/events/* >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.httpd %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility @@ -272,7 +271,6 @@ ln -sf %{_sysconfdir}/zm/www/zoneminder.httpd.conf %{_sysconfdir}/zm/www/zonemin # For the case of changing from httpd <-> nginx, files in these folders must change ownership if they exist %{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/php/session/* >/dev/null 2>&1 || : %{_bindir}/chown -R nginx:nginx %{_localstatedir}/log/zoneminder/* >/dev/null 2>&1 || : -%{_bindir}/chown -R nginx:nginx %{_sharedstatedir}/zoneminder/events/* >/dev/null 2>&1 || : ln -sf %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules # backwards compatibility From 279255d979f5a9772de5e0dc62631f484b87589f Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 30 Nov 2018 08:58:42 -0600 Subject: [PATCH 166/240] rpm pkg - update README --- distros/redhat/readme/README | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/distros/redhat/readme/README b/distros/redhat/readme/README index b26a4e2f8..0b3e4bb9c 100644 --- a/distros/redhat/readme/README +++ b/distros/redhat/readme/README @@ -19,9 +19,8 @@ What's New zoneminder-nginx - Files needed for compatibility with the Nginx web server You can switch between different subpackages with dnf/yum. Be advised that, - switching between httpd <-> nginx may not be perfect. Several files and - folders need to change ownership. The package attempts to do this, but - manual intervention will still likely be needed. + switching between httpd <-> nginx requires manaully changing ownership of + all event folders and the php session folder after the change. 4. If you have installed ZoneMinder from the FedBerry repositories, this build of ZoneMinder has support for Raspberry Pi hardware acceleration when using From f9139f2d98051d5dced27435482217893b74f29d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Nov 2018 10:48:20 -0500 Subject: [PATCH 167/240] Use the word skipped instead of aborted --- scripts/zmupdate.pl.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index 45d45851a..8517e0277 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -353,8 +353,8 @@ if ( $version ) { $version = $detaint_version; if ( ZM_VERSION eq $version ) { - print( "\nDatabase already at version $version, update aborted.\n\n" ); - exit( 0 ); + print("\nDatabase already at version $version, update skipped.\n\n"); + exit(0); } print( "\nInitiating database upgrade to version ".ZM_VERSION." from version $version\n" ); From 8c626c984b0d7504efa9fcd74cd9e5f39238b188 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Nov 2018 14:45:58 -0500 Subject: [PATCH 168/240] Need to pass port through all Url functions --- web/includes/Server.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/includes/Server.php b/web/includes/Server.php index 06219a1f5..3918e9389 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -84,8 +84,8 @@ class Server { } } - public function UrlToZMS( ) { - return $this->Url().$this->PathToZMS(); + public function UrlToZMS( $port = null ) { + return $this->Url($port).$this->PathToZMS(); } public function Url( $port = null ) { @@ -113,11 +113,11 @@ class Server { return $_SERVER['PHP_SELF']; } - public function UrlToIndex( ) { - return $this->Url().$this->PathToIndex(); + public function UrlToIndex( $port=null ) { + return $this->Url($port).$this->PathToIndex(); } - public function UrlToApi( ) { - return $this->Url().$this->PathToApi(); + public function UrlToApi( $port=null ) { + return $this->Url($port).$this->PathToApi(); } public function PathToApi( $new = null ) { if ( $new != null ) From 6ad54aad930372048b13ca575ffe206939c4a029 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 30 Nov 2018 14:53:31 -0500 Subject: [PATCH 169/240] add libswscale5 to depends for ubuntu cosmic --- distros/ubuntu1604/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index e487d17b6..991ed9e54 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -41,7 +41,7 @@ Package: zoneminder Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,javascript-common - ,libmp4v2-2, libx264-142|libx264-148|libx264-152, libswscale-ffmpeg3|libswscale4|libswscale3 + ,libmp4v2-2, libx264-142|libx264-148|libx264-152, libswscale-ffmpeg3|libswscale4|libswscale3|libswscale5 ,ffmpeg | libav-tools ,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl ,libdbd-mysql-perl From 76e0782d97f8fde02c152d0c7f8e7abd5296bafa Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 1 Dec 2018 09:58:12 -0600 Subject: [PATCH 170/240] rpm pkg - update nginx config --- distros/redhat/CMakeLists.txt | 2 + distros/redhat/nginx/redirect.nginx.conf | 2 + distros/redhat/nginx/zoneminder.nginx.conf.in | 90 ++++++++++--------- distros/redhat/readme/README.nginx | 9 +- distros/redhat/zoneminder.spec | 1 + 5 files changed, 58 insertions(+), 46 deletions(-) create mode 100644 distros/redhat/nginx/redirect.nginx.conf diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index 716faea4c..06b0e8cbf 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -32,6 +32,7 @@ configure_file(httpd/com.zoneminder.systemctl.rules.httpd.in ${CMAKE_CURRENT_SOU # Configure the Nginx zoneminder files configure_file(nginx/zm-nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-nginx.conf COPYONLY) configure_file(nginx/zoneminder.nginx.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.conf @ONLY) +configure_file(nginx/redirect.nginx.conf ${CMAKE_CURRENT_SOURCE_DIR}/redirect.nginx.conf COPYONLY) configure_file(nginx/zoneminder.nginx.tmpfiles.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.nginx.tmpfiles.conf @ONLY) configure_file(nginx/zm-web-user.conf ${CMAKE_CURRENT_SOURCE_DIR}/zm-web-user.conf COPYONLY) configure_file(nginx/zoneminder.php-fpm.conf ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.php-fpm.conf COPYONLY) @@ -62,6 +63,7 @@ install(FILES com.zoneminder.systemctl.rules.httpd DESTINATION /etc/zm/www PERMI # Install the Nginx zoneminder files install(FILES zm-nginx.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +install(FILES redirect.nginx.conf DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zoneminder.nginx.tmpfiles.conf DESTINATION /usr/lib/tmpfiles.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES com.zoneminder.systemctl.rules.nginx DESTINATION /etc/zm/www PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) install(FILES zm-web-user.conf DESTINATION /etc/zm/conf.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/distros/redhat/nginx/redirect.nginx.conf b/distros/redhat/nginx/redirect.nginx.conf new file mode 100644 index 000000000..67ef08124 --- /dev/null +++ b/distros/redhat/nginx/redirect.nginx.conf @@ -0,0 +1,2 @@ +# Auto redirect to https +return 301 https://$host$request_uri; diff --git a/distros/redhat/nginx/zoneminder.nginx.conf.in b/distros/redhat/nginx/zoneminder.nginx.conf.in index fb8141c74..c2e3edee7 100644 --- a/distros/redhat/nginx/zoneminder.nginx.conf.in +++ b/distros/redhat/nginx/zoneminder.nginx.conf.in @@ -1,53 +1,57 @@ -listen 443 ssl; -listen [::]:443 ssl; +server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + server_name = localhost $hostname; -ssl_certificate "/etc/pki/tls/certs/localhost.crt"; -ssl_certificate_key "/etc/pki/tls/private/localhost.key"; -ssl_session_cache shared:SSL:1m; -ssl_session_timeout 10m; -ssl_ciphers PROFILE=SYSTEM; -ssl_prefer_server_ciphers on; + ssl_certificate "/etc/pki/tls/certs/localhost.crt"; + ssl_certificate_key "/etc/pki/tls/private/localhost.key"; + ssl_session_cache shared:SSL:1m; + ssl_session_timeout 10m; + ssl_ciphers PROFILE=SYSTEM; + ssl_prefer_server_ciphers on; -# Auto-redirect HTTP requests to HTTPS -if ($scheme != "https") { - rewrite ^/?(zm)(.*)$ https://$host/$1$2 permanent; -} - -location /cgi-bin-zm { - gzip off; - alias "@ZM_CGIDIR@"; - - include /etc/nginx/fastcgi_params; - fastcgi_param SCRIPT_FILENAME $request_filename; - fastcgi_pass unix:/run/fcgiwrap.sock; -} - -location /zm/cache { - alias "@ZM_CACHEDIR@"; -} - -location /zm { - gzip off; - alias "@ZM_WEBDIR@"; - index index.php; - - location ~ \.php$ { - if (!-f $request_filename) { return 404; } - expires epoch; - include /etc/nginx/fastcgi_params; - fastcgi_param SCRIPT_FILENAME $request_filename; - fastcgi_index index.php; - fastcgi_pass unix:/run/php-fpm/www.sock; + # Auto redirect to server/zm when no url suffix was given + location = / { + return 301 zm; } - location ~ \.(jpg|jpeg|gif|png|ico)$ { - access_log off; - expires 33d; + location /cgi-bin-zm { + gzip off; + alias "@ZM_CGIDIR@"; + + include /etc/nginx/fastcgi_params; + fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_pass unix:/run/fcgiwrap.sock; } - location /zm/api/ { + location /zm/cache { + alias "@ZM_CACHEDIR@"; + } + + location /zm { + gzip off; alias "@ZM_WEBDIR@"; - rewrite ^/zm/api(.+)$ /zm/api/app/webroot/index.php?p=$1 last; + index index.php; + + location ~ \.php$ { + try_files $uri =404; + expires epoch; + include /etc/nginx/fastcgi_params; + fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_index index.php; + fastcgi_pass unix:/run/php-fpm/www.sock; + } + + location ~ \.(jpg|jpeg|gif|png|ico)$ { + access_log off; + expires 33d; + } + + location /zm/api/ { + alias "@ZM_WEBDIR@"; + rewrite ^/zm/api(.+)$ /zm/api/app/webroot/index.php?p=$1 last; + } } + } diff --git a/distros/redhat/readme/README.nginx b/distros/redhat/readme/README.nginx index b55d26428..cca4e72c2 100644 --- a/distros/redhat/readme/README.nginx +++ b/distros/redhat/readme/README.nginx @@ -61,8 +61,7 @@ New installs 6. Configure the web server This package uses the HTTPS protocol by default to access the web portal, - using the default self signed certificate on your system. Requests using - HTTP will auto-redirect to HTTPS. + using the default self signed certificate on your system. Inspect the web server configuration file and verify it meets your needs: @@ -71,9 +70,13 @@ New installs If you are running other web enabled services then you may need to edit this file to suite. See README.https to learn about other alternatives. + If you wish http requests to auto-redirect to https requests, then link or + copy /etc/zm/www/redirect.nginx.conf into /etc/nginx/default.d folder. + When in doubt, proceed with the default: - sudo ln -sf /etc/zm/www/zoneminder.nginx.conf /etc/nginx/default.d/ + sudo ln -sf /etc/zm/www/zoneminder.nginx.conf /etc/nginx/conf.d/ + sudo ln -sf /etc/zm/www/redirect.nginx.conf /etc/nginx/default.d/ 7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of simulatneous streams the server should support. Generally, a good minimum diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 59fd3dc81..734a70a25 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -390,6 +390,7 @@ EOF %config(noreplace) %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/*.conf %ghost %attr(640,root,nginx) %{_sysconfdir}/zm/conf.d/zmcustom.conf %config(noreplace) %{_sysconfdir}/zm/www/zoneminder.nginx.conf +%config(noreplace) %{_sysconfdir}/zm/www/redirect.nginx.conf %ghost %{_sysconfdir}/zm/www/zoneminder.conf %config(noreplace) %{_sysconfdir}/zm/www/com.zoneminder.systemctl.rules.nginx %ghost %{_datadir}/polkit-1/rules.d/com.zoneminder.systemctl.rules From cae6ffd5a3c781da5830fe9c8568c6275e6c4def Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 1 Dec 2018 13:27:08 -0600 Subject: [PATCH 171/240] use HTTP_HOST instead of SERVER_NAME --- web/includes/Server.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/includes/Server.php b/web/includes/Server.php index 3918e9389..dae6cd7c2 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -51,7 +51,8 @@ class Server { } else if ( $this->Id() ) { return $this->{'Name'}; } - return $_SERVER['SERVER_NAME']; + # Use HTTP_HOST instead of SERVER_NAME here for nginx compatiblity + return $_SERVER['HTTP_HOST']; } public function Protocol( $new = null ) { @@ -93,7 +94,8 @@ class Server { if ( $this->Id() ) { $url .= $this->Hostname(); } else { - $url .= $_SERVER['SERVER_NAME']; + # Use HTTP_HOST instead of SERVER_NAME here for nginx compatiblity + $url .= $_SERVER['HTTP_HOST']; } if ( $port ) { $url .= ':'.$port; From e327ad100eef72662b540f11c31e5b7da57e2fe3 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 1 Dec 2018 17:03:50 -0600 Subject: [PATCH 172/240] fix WebSite camera startup issue --- web/includes/actions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index de0861fe0..1e560f694 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -617,7 +617,7 @@ if ( canEdit('Monitors') ) { $new_monitor = new Monitor($mid); //fixDevices(); - if ( $monitor['Type'] != 'WebSite' ) { + if ( $new_monitor->Type() != 'WebSite' ) { $new_monitor->zmcControl('start'); $new_monitor->zmaControl('start'); } From dbb51e985785062d02a30152c89ac02be2aaf46e Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sun, 2 Dec 2018 09:40:15 -0600 Subject: [PATCH 173/240] add generic nginx config file --- misc/CMakeLists.txt | 1 + misc/nginx.conf.in | 61 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 misc/nginx.conf.in diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt index 3f92bd5da..990b8ce06 100644 --- a/misc/CMakeLists.txt +++ b/misc/CMakeLists.txt @@ -2,6 +2,7 @@ # Create files from the .in files configure_file(apache.conf.in "${CMAKE_CURRENT_BINARY_DIR}/apache.conf" @ONLY) +configure_file(nginx.conf.in "${CMAKE_CURRENT_BINARY_DIR}/nginx.conf" @ONLY) configure_file(logrotate.conf.in "${CMAKE_CURRENT_BINARY_DIR}/logrotate.conf" @ONLY) configure_file(syslog.conf.in "${CMAKE_CURRENT_BINARY_DIR}/syslog.conf" @ONLY) configure_file(com.zoneminder.systemctl.policy.in "${CMAKE_CURRENT_BINARY_DIR}/com.zoneminder.systemctl.policy" @ONLY) diff --git a/misc/nginx.conf.in b/misc/nginx.conf.in new file mode 100644 index 000000000..47dc3ce68 --- /dev/null +++ b/misc/nginx.conf.in @@ -0,0 +1,61 @@ +# +# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION +# + +server { + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + server_name = localhost $hostname; + + ssl_certificate "/etc/pki/tls/certs/localhost.crt"; + ssl_certificate_key "/etc/pki/tls/private/localhost.key"; + ssl_session_cache shared:SSL:1m; + ssl_session_timeout 10m; + ssl_ciphers PROFILE=SYSTEM; + ssl_prefer_server_ciphers on; + + # Auto redirect to server/zm when no url suffix was given + location = / { + return 301 zm; + } + + location /cgi-bin-zm { + gzip off; + alias "@ZM_CGIDIR@"; + + include /etc/nginx/fastcgi_params; + fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_pass unix:/run/fcgiwrap.sock; + } + + location /zm/cache { + alias "@ZM_CACHEDIR@"; + } + + location /zm { + gzip off; + alias "@ZM_WEBDIR@"; + index index.php; + + location ~ \.php$ { + try_files $uri =404; + expires epoch; + include /etc/nginx/fastcgi_params; + fastcgi_param SCRIPT_FILENAME $request_filename; + fastcgi_index index.php; + fastcgi_pass unix:/run/php-fpm/www.sock; + } + + location ~ \.(jpg|jpeg|gif|png|ico)$ { + access_log off; + expires 33d; + } + + location /zm/api/ { + alias "@ZM_WEBDIR@"; + rewrite ^/zm/api(.+)$ /zm/api/app/webroot/index.php?p=$1 last; + } + } + +} + From d837b4283632aa6c39efaca09561acdfc6abb1b2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 3 Dec 2018 10:33:53 -0500 Subject: [PATCH 174/240] fix ffmpeg warnings. We have to copy parameters from the context to the stream AFTER we open the codec --- src/zm_videostore.cpp | 124 ++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 76 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index a3b66646b..746036efe 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -238,7 +238,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec); #endif if ( !audio_out_stream ) { - Error("Unable to create audio out stream\n"); + Error("Unable to create audio out stream"); audio_out_stream = NULL; } else { Debug(2, "setting parameters"); @@ -265,7 +265,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, Debug(2, "Setting audio codec tag to %d", audio_out_ctx->codec_tag); } - #else audio_out_ctx = audio_out_stream->codec; ret = avcodec_copy_context(audio_out_ctx, audio_in_ctx); @@ -287,7 +286,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, } // end if is AAC if ( audio_out_stream ) { - if (oc->oformat->flags & AVFMT_GLOBALHEADER) { + if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) { #if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0) audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; #else @@ -297,7 +296,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, } } // end if audio_in_stream - video_last_pts = 0; video_last_dts = 0; audio_last_pts = 0; @@ -310,12 +308,11 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, bool VideoStore::open() { /* open the out file, if needed */ - if (!(out_format->flags & AVFMT_NOFILE)) { + if ( !(out_format->flags & AVFMT_NOFILE) ) { ret = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL); - if (ret < 0) { + if ( ret < 0 ) { Error("Could not open out file '%s': %s\n", filename, av_make_error_string(ret).c_str()); - return false; } } @@ -339,9 +336,9 @@ bool VideoStore::open() { } else if (av_dict_count(opts) != 0) { Warning("some options not set\n"); } - if (opts) av_dict_free(&opts); - if (ret < 0) { - Error("Error occurred when writing out file header to %s: %s\n", + if ( opts ) av_dict_free(&opts); + if ( ret < 0 ) { + Error("Error occurred when writing out file header to %s: %s", filename, av_make_error_string(ret).c_str()); /* free the stream */ avio_closep(&oc->pb); @@ -506,13 +503,13 @@ bool VideoStore::setup_resampler() { avcodec_find_decoder(audio_in_ctx->codec_id); #endif ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL); - if (ret < 0) { + if ( ret < 0 ) { Error("Can't open in codec!"); return false; } audio_out_codec = avcodec_find_encoder(AV_CODEC_ID_AAC); - if (!audio_out_codec) { + if ( !audio_out_codec ) { Error("Could not find codec for AAC"); return false; } @@ -521,7 +518,6 @@ bool VideoStore::setup_resampler() { #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) // audio_out_ctx = audio_out_stream->codec; audio_out_ctx = avcodec_alloc_context3(audio_out_codec); - if ( !audio_out_ctx ) { Error("could not allocate codec ctx for AAC"); audio_out_stream = NULL; @@ -530,7 +526,7 @@ bool VideoStore::setup_resampler() { Debug(2, "Have audio_out_ctx"); // Now copy them to the out stream - audio_out_stream = avformat_new_stream(oc, NULL); + audio_out_stream = avformat_new_stream(oc, audio_out_codec); #else audio_out_stream = avformat_new_stream(oc, NULL); audio_out_ctx = audio_out_stream->codec; @@ -554,28 +550,27 @@ bool VideoStore::setup_resampler() { audio_out_ctx->channel_layout = av_get_default_channel_layout(audio_out_ctx->channels); } - if (audio_out_codec->supported_samplerates) { + if ( audio_out_codec->supported_samplerates ) { int found = 0; - for (unsigned int i = 0; audio_out_codec->supported_samplerates[i]; - i++) { - if (audio_out_ctx->sample_rate == - audio_out_codec->supported_samplerates[i]) { + for ( unsigned int i = 0; audio_out_codec->supported_samplerates[i]; i++) { + if ( audio_out_ctx->sample_rate == + audio_out_codec->supported_samplerates[i] ) { found = 1; break; } } - if (found) { + if ( found ) { Debug(3, "Sample rate is good"); } else { audio_out_ctx->sample_rate = audio_out_codec->supported_samplerates[0]; - Debug(1, "Sampel rate is no good, setting to (%d)", + Debug(1, "Sample rate is no good, setting to (%d)", audio_out_codec->supported_samplerates[0]); } } /* check that the encoder supports s16 pcm in */ - if (!check_sample_fmt(audio_out_codec, audio_out_ctx->sample_fmt)) { + if ( !check_sample_fmt(audio_out_codec, audio_out_ctx->sample_fmt) ) { Debug(3, "Encoder does not support sample format %s, setting to FLTP", av_get_sample_fmt_name(audio_out_ctx->sample_fmt)); audio_out_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP; @@ -584,16 +579,6 @@ bool VideoStore::setup_resampler() { audio_out_ctx->time_base = (AVRational){1, audio_out_ctx->sample_rate}; - -#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) - ret = avcodec_parameters_from_context(audio_out_stream->codecpar, - audio_out_ctx); - if (ret < 0) { - Error("Could not initialize stream parameteres"); - return false; - } -#endif - AVDictionary *opts = NULL; if ( (ret = av_dict_set(&opts, "strict", "experimental", 0)) < 0 ) { Error("Couldn't set experimental"); @@ -608,6 +593,15 @@ bool VideoStore::setup_resampler() { return false; } +#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) + ret = avcodec_parameters_from_context( + audio_out_stream->codecpar, audio_out_ctx); + if ( ret < 0 ) { + Error("Could not initialize stream parameteres"); + return false; + } +#endif + Debug(1, "Audio out bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) " "layout(%d) frame_size(%d)", @@ -616,13 +610,13 @@ bool VideoStore::setup_resampler() { audio_out_ctx->channel_layout, audio_out_ctx->frame_size); /** Create a new frame to store the audio samples. */ - if (!(in_frame = zm_av_frame_alloc())) { + if ( !(in_frame = zm_av_frame_alloc()) ) { Error("Could not allocate in frame"); return false; } /** Create a new frame to store the audio samples. */ - if (!(out_frame = zm_av_frame_alloc())) { + if ( !(out_frame = zm_av_frame_alloc()) ) { Error("Could not allocate out frame"); av_frame_free(&in_frame); return false; @@ -630,20 +624,20 @@ bool VideoStore::setup_resampler() { // Setup the audio resampler resample_ctx = avresample_alloc_context(); - if (!resample_ctx) { - Error("Could not allocate resample ctx\n"); + if ( !resample_ctx ) { + Error("Could not allocate resample ctx"); return false; } // Some formats (i.e. WAV) do not produce the proper channel layout - if (audio_in_ctx->channel_layout == 0) { - uint64_t layout = av_get_channel_layout("mono"); - av_opt_set_int(resample_ctx, "in_channel_layout", - av_get_channel_layout("mono"), 0); - Debug(1, "Bad channel layout. Need to set it to mono (%d).", layout); + uint64_t layout = av_get_channel_layout("mono"); + if ( audio_in_ctx->channel_layout == 0 ) { + av_opt_set_int(resample_ctx, "in_channel_layout", layout, 0); + Debug(1, "Bad in channel layout. Need to set it to mono (%d).", layout); } else { av_opt_set_int(resample_ctx, "in_channel_layout", audio_in_ctx->channel_layout, 0); + layout = audio_in_ctx->channel_layout; } av_opt_set_int(resample_ctx, "in_sample_fmt", @@ -655,7 +649,7 @@ bool VideoStore::setup_resampler() { // av_opt_set_int( resample_ctx, "out_channel_layout", // audio_out_ctx->channel_layout, 0); av_opt_set_int(resample_ctx, "out_channel_layout", - av_get_channel_layout("mono"), 0); + layout, 0); av_opt_set_int(resample_ctx, "out_sample_fmt", audio_out_ctx->sample_fmt, 0); av_opt_set_int(resample_ctx, "out_sample_rate", @@ -664,38 +658,13 @@ bool VideoStore::setup_resampler() { audio_out_ctx->channels, 0); ret = avresample_open(resample_ctx); - if (ret < 0) { - Error("Could not open resample ctx\n"); + if ( ret < 0 ) { + Error("Could not open resample ctx"); return false; + } else { + Debug(2, "Success opening resampler"); } -#if 0 - /** - * Allocate as many pointers as there are audio channels. - * Each pointer will later point to the audio samples of the corresponding - * channels (although it may be NULL for interleaved formats). - */ - if (!( converted_in_samples = reinterpret_castcalloc( audio_out_ctx->channels, sizeof(*converted_in_samples))) ) { - Error("Could not allocate converted in sample pointers\n"); - return; - } - /** - * Allocate memory for the samples of all channels in one consecutive - * block for convenience. - */ - if ( (ret = av_samples_alloc( &converted_in_samples, NULL, - audio_out_ctx->channels, - audio_out_ctx->frame_size, - audio_out_ctx->sample_fmt, 0)) < 0 ) { - Error("Could not allocate converted in samples (error '%s')\n", - av_make_error_string(ret).c_str()); - - av_freep(converted_in_samples); - free(converted_in_samples); - return; - } -#endif - out_frame->nb_samples = audio_out_ctx->frame_size; out_frame->format = audio_out_ctx->sample_fmt; out_frame->channel_layout = audio_out_ctx->channel_layout; @@ -703,21 +672,24 @@ bool VideoStore::setup_resampler() { // The codec gives us the frame size, in samples, we calculate the size of the // samples buffer in bytes unsigned int audioSampleBuffer_size = av_samples_get_buffer_size( - NULL, audio_out_ctx->channels, audio_out_ctx->frame_size, + NULL, audio_out_ctx->channels, + audio_out_ctx->frame_size, audio_out_ctx->sample_fmt, 0); converted_in_samples = (uint8_t *)av_malloc(audioSampleBuffer_size); - if (!converted_in_samples) { - Error("Could not allocate converted in sample pointers\n"); + if ( !converted_in_samples ) { + Error("Could not allocate converted in sample pointers"); return false; + } else { + Debug(2, "Frame Size %d, sample buffer size %d", audio_out_ctx->frame_size, audioSampleBuffer_size); } // Setup the data pointers in the AVFrame - if (avcodec_fill_audio_frame(out_frame, audio_out_ctx->channels, + if ( avcodec_fill_audio_frame(out_frame, audio_out_ctx->channels, audio_out_ctx->sample_fmt, (const uint8_t *)converted_in_samples, audioSampleBuffer_size, 0) < 0) { - Error("Could not allocate converted in sample pointers\n"); + Error("Could not allocate converted in sample pointers"); return false; } From 27d4ba9e5f296d5e529c1d5e5e3b4e1084302247 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 3 Dec 2018 15:16:47 -0500 Subject: [PATCH 175/240] use output of babeljs.io to provide code that works on older browsers. The nice class notation is ES6 upwards.. Safari on IOS9 doesn't like it --- web/js/Server.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/web/js/Server.js b/web/js/Server.js index 6e3254f65..61d1ff713 100644 --- a/web/js/Server.js +++ b/web/js/Server.js @@ -1,12 +1,28 @@ -class Server { - constructor(json) { - for( var k in json ) { +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Server = function () { + function Server(json) { + _classCallCheck(this, Server); + + for (var k in json) { this[k] = json[k]; } } - url(port=0){ - return location.protocol+'//'+this.Hostname+ - (port ? ':'+port : '') + - ( ( this.PathPrefix && this.PathPrefix != 'null') ? this.PathPrefix : ''); - } -}; + + _createClass(Server, [{ + key: 'url', + value: function url() { + var port = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + + return location.protocol + '//' + this.Hostname + (port ? ':' + port : '') + (this.PathPrefix && this.PathPrefix != 'null' ? this.PathPrefix : ''); + } + }]); + + return Server; +}(); + +; From 18ce7c9ea007d49ff8ed3e311125e3610a8b7037 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 3 Dec 2018 15:17:16 -0500 Subject: [PATCH 176/240] Old browsers, specifically Safari on IOS9 doesn't support let. Need to use var instead. --- web/skins/classic/js/skin.js | 24 ++++---- web/skins/classic/views/js/event.js | 66 ++++++++++---------- web/skins/classic/views/js/filter.js | 92 ++++++++++++++-------------- 3 files changed, 91 insertions(+), 91 deletions(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index e4eed0597..ded2d8ca4 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -319,11 +319,11 @@ function convertLabelFormat(LabelFormat, monitorName){ function addVideoTimingTrack(video, LabelFormat, monitorName, duration, startTime){ //This is a hacky way to handle changing the texttrack. If we ever upgrade vjs in a revamp replace this. Old method preserved because it's the right way. - let cues = vid.textTracks()[0].cues(); - let labelFormat = convertLabelFormat(LabelFormat, monitorName); + var cues = vid.textTracks()[0].cues(); + var labelFormat = convertLabelFormat(LabelFormat, monitorName); startTime = moment(startTime); - for (let i = 0; i <= duration; i++) { + for (var i = 0; i <= duration; i++) { cues[i] = {id: i, index: i, startTime: i, Ca: i+1, text: startTime.format(labelFormat)}; startTime.add(1, 's'); } @@ -361,21 +361,21 @@ function endOfResize(e) { function scaleToFit (baseWidth, baseHeight, scaleEl, bottomEl) { $j(window).on('resize', endOfResize) //set delayed scaling when Scale to Fit is selected - let ratio = baseWidth / baseHeight; - let container = $j('#content'); - let viewPort = $j(window); + var ratio = baseWidth / baseHeight; + var container = $j('#content'); + var viewPort = $j(window); // jquery does not provide a bottom offet, and offset dows not include margins. outerHeight true minus false gives total vertical margins. - let bottomLoc = bottomEl.offset().top + (bottomEl.outerHeight(true) - bottomEl.outerHeight()) + bottomEl.outerHeight(true); - let newHeight = viewPort.height() - (bottomLoc - scaleEl.outerHeight(true)) - let newWidth = ratio * newHeight; + var bottomLoc = bottomEl.offset().top + (bottomEl.outerHeight(true) - bottomEl.outerHeight()) + bottomEl.outerHeight(true); + var newHeight = viewPort.height() - (bottomLoc - scaleEl.outerHeight(true)) + var newWidth = ratio * newHeight; if (newWidth > container.innerWidth()) { newWidth = container.innerWidth(); newHeight = newWidth / ratio; } - let autoScale = Math.round(newWidth / baseWidth * SCALE_BASE); - let scales = $j('#scale option').map(function() {return parseInt($j(this).val());}).get(); + var autoScale = Math.round(newWidth / baseWidth * SCALE_BASE); + var scales = $j('#scale option').map(function() {return parseInt($j(this).val());}).get(); scales.shift(); - let closest; + var closest; $j(scales).each(function () { //Set zms scale to nearest regular scale. Zoom does not like arbitrary scale values. if (closest == null || Math.abs(this - autoScale) < Math.abs(closest - autoScale)) { closest = this.valueOf(); diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 9981b1458..e2f913ede 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -1,7 +1,7 @@ var vid = null; function vjsReplay() { - let endTime = (Date.parse(eventData.EndTime)).getTime(); + var endTime = (Date.parse(eventData.EndTime)).getTime(); switch(replayMode.value) { case 'none': break; @@ -10,22 +10,22 @@ function vjsReplay() { break; case 'all': if (nextEventId == 0) { - let overLaid = $j("#videoobj"); + var overLaid = $j("#videoobj"); overLaid.append('

No more events

'); } else { - let nextStartTime = nextEventStartTime.getTime(); //nextEventStartTime.getTime() is a mootools workaround, highjacks Date.parse + var nextStartTime = nextEventStartTime.getTime(); //nextEventStartTime.getTime() is a mootools workaround, highjacks Date.parse if (nextStartTime <= endTime) { streamNext( true ); return; } - let overLaid = $j("#videoobj"); + var overLaid = $j("#videoobj"); vid.pause(); overLaid.append('

'); - let gapDuration = (new Date().getTime()) + (nextStartTime - endTime); - let messageP = $j(".vjsMessage"); - let x = setInterval(function() { - let now = new Date().getTime(); - let remainder = new Date(Math.round(gapDuration - now)).toISOString().substr(11,8); + var gapDuration = (new Date().getTime()) + (nextStartTime - endTime); + var messageP = $j(".vjsMessage"); + var x = setInterval(function() { + var now = new Date().getTime(); + var remainder = new Date(Math.round(gapDuration - now)).toISOString().substr(11,8); messageP.html(remainder + ' to next event.'); if (remainder < 0) { clearInterval(x); @@ -70,7 +70,7 @@ function renderAlarmCues (containerEl) { var pixSkew = 0; var skip = 0; var num_cueFrames = cueFrames.length; - for ( let i = 0; i < num_cueFrames; i++ ) { + for ( var i = 0; i < num_cueFrames; i++ ) { skip = 0; frame = cueFrames[i]; if (frame.Type == "Alarm" && alarmed == 0) { //From nothing to alarm. End nothing and start alarm. @@ -78,7 +78,7 @@ var num_cueFrames = cueFrames.length; if (frame.Delta == 0) continue; //If event starts with an alarm or too few for a nonespan spanTimeEnd = frame.Delta * 100; spanTime = spanTimeEnd - spanTimeStart; - let pix = cueRatio * spanTime; + var pix = cueRatio * spanTime; pixSkew += pix - Math.round(pix);//average out the rounding errors. pix = Math.round(pix); if ((pixSkew > 1 || pixSkew < -1) && pix + Math.round(pixSkew) > 0) { //add skew if it's a pixel and won't zero out span. @@ -143,20 +143,20 @@ function setButtonState( element, butClass ) { } function changeScale() { - let scale = $j('#scale').val(); - let newWidth; - let newHeight; - let autoScale; - let eventViewer; - let alarmCue = $j('div.alarmCue'); - let bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus'); + var scale = $j('#scale').val(); + var newWidth; + var newHeight; + var autoScale; + var eventViewer; + var alarmCue = $j('div.alarmCue'); + var bottomEl = streamMode == 'stills' ? $j('#eventImageNav') : $j('#replayStatus'); if (streamMode == 'stills') { eventViewer = $j('#eventThumbs'); } else { eventViewer = $j(vid ? '#videoobj' : '#evtStream'); } if ( scale == "auto" ) { - let newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl); + var newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl); newWidth = newSize.width; newHeight = newSize.height; autoScale = newSize.autoScale; @@ -419,8 +419,8 @@ function streamNext(action) { $j(".vjsMessage").remove();//This shouldn't happen if ( nextEventId == 0 ) { //handles deleting last event. pauseClicked(); - let hideContainer = $j('#eventVideo'); - let hideStream = $j(vid ? "#videoobj" : "#evtStream").height() + (vid ? 0 :$j("#progressBar").height()); + var hideContainer = $j('#eventVideo'); + var hideStream = $j(vid ? "#videoobj" : "#evtStream").height() + (vid ? 0 :$j("#progressBar").height()); hideContainer.prepend('

No more events

'); if ( vid == null ) zmsBroke = true; return; @@ -443,15 +443,15 @@ function streamNext(action) { } function vjsPanZoom (action, x, y) { //Pan and zoom with centering where the click occurs - let outer = $j('#videoobj'); - let video = outer.children().first(); - let zoom = parseFloat($j('#zoomValue').html()); - let zoomRate = .5; - let matrix = video.css('transform').split(','); - let currentPanX = parseFloat(matrix[4]); - let currentPanY = parseFloat(matrix[5]); - let xDist = outer.width()/2 - x //Click distance from center of view - let yDist = outer.height()/2 - y + var outer = $j('#videoobj'); + var video = outer.children().first(); + var zoom = parseFloat($j('#zoomValue').html()); + var zoomRate = .5; + var matrix = video.css('transform').split(','); + var currentPanX = parseFloat(matrix[4]); + var currentPanY = parseFloat(matrix[5]); + var xDist = outer.width()/2 - x //Click distance from center of view + var yDist = outer.height()/2 - y if (action == 'zoomOut') { zoom -= zoomRate; if (x && y) { @@ -476,8 +476,8 @@ function vjsPanZoom (action, x, y) { //Pan and zoom with centering where the cli x = xDist + currentPanX; y = yDist + currentPanY; } - let limitX = ((zoom*outer.width()) - outer.width())/2; //Calculate outer bounds of video - let limitY = ((zoom*outer.height()) - outer.height())/2; + var limitX = ((zoom*outer.width()) - outer.width())/2; //Calculate outer bounds of video + var limitY = ((zoom*outer.height()) - outer.height())/2; x = Math.min(Math.max((x),-limitX),limitX); //Limit pan to outer bounds of video y = Math.min(Math.max((y),-limitY),limitY); video.css('transform', 'matrix('+zoom+', 0, 0, '+zoom+', '+x+', '+y+')'); @@ -950,7 +950,7 @@ function videoEvent() { // Called on each event load because each event can be a different width function drawProgressBar() { - let barWidth = $j('#evtStream').width(); + var barWidth = $j('#evtStream').width(); $j('#progressBar').css( 'width', barWidth ); } diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js index f752dbff7..461025b1a 100644 --- a/web/skins/classic/views/js/filter.js +++ b/web/skins/classic/views/js/filter.js @@ -1,8 +1,8 @@ function validateForm ( form ) { - let rows = $j(form).find('tbody').eq(0).find('tr'); - let obrCount = 0; - let cbrCount = 0; - for ( let i = 0; i < rows.length; i++ ) { + var rows = $j(form).find('tbody').eq(0).find('tr'); + var obrCount = 0; + var cbrCount = 0; + for ( var i = 0; i < rows.length; i++ ) { if (rows.length > 2) { obrCount += parseInt(form.elements['filter[Query][terms][' + i + '][obr]'].value); cbrCount += parseInt(form.elements['filter[Query][terms][' + i + '][cbr]'].value); @@ -59,7 +59,7 @@ function updateButtons( element ) { } function checkValue ( element ) { - let rows = $j(element).closest('tbody').children(); + var rows = $j(element).closest('tbody').children(); parseRows(rows); //clearValue(element); } @@ -103,32 +103,32 @@ function deleteFilter( element, name ) { } function parseRows (rows) { - for (let rowNum = 0; rowNum < rows.length; rowNum++) { //Each row is a term - let queryPrefix = 'filter[Query][terms]['; - let inputTds = rows.eq(rowNum).children(); + 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+ - let cnjVal = inputTds.eq(0).children().val(); - let conjSelect = $j('').attr('name', queryPrefix + rowNum + '][cnj]').attr('id', queryPrefix + rowNum + '][cnj]'); + 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) { conjSelect.append(''); }); inputTds.eq(0).html(conjSelect).children().val(cnjVal === undefined ? 'and' : cnjVal); } - let brackets = rows.length - 2; + var brackets = rows.length - 2; if (brackets > 0) { //add bracket select to all rows - let obrSelect = $j('').attr('name', queryPrefix + rowNum + '][obr]').attr('id', queryPrefix + rowNum + '][obr]'); - let cbrSelect = $j('').attr('name', queryPrefix + rowNum + '][cbr]').attr('id', queryPrefix + rowNum + '][cbr]'); + var obrSelect = $j('').attr('name', queryPrefix + rowNum + '][obr]').attr('id', queryPrefix + rowNum + '][obr]'); + var cbrSelect = $j('').attr('name', queryPrefix + rowNum + '][cbr]').attr('id', queryPrefix + rowNum + '][cbr]'); obrSelect.append(''); cbrSelect.append(''); } - let obrVal = inputTds.eq(1).children().val() != undefined ? inputTds.eq(1).children().val() : 0; //Save currently selected bracket option - let cbrVal = inputTds.eq(5).children().val() != undefined ? inputTds.eq(5).children().val() : 0; + var obrVal = inputTds.eq(1).children().val() != undefined ? inputTds.eq(1).children().val() : 0; //Save currently selected bracket option + var cbrVal = inputTds.eq(5).children().val() != undefined ? inputTds.eq(5).children().val() : 0; inputTds.eq(1).html(obrSelect).children().val(obrVal); //Set bracket contents and assign saved value inputTds.eq(5).html(cbrSelect).children().val(cbrVal); } else { @@ -146,61 +146,61 @@ function parseRows (rows) { if ( attr == "Archived") { //Archived types inputTds.eq(3).html('equal to'); - let archiveSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); - for (let i = 0; i < archiveTypes.length; i++) { + var archiveSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + for (var i = 0; i < archiveTypes.length; i++) { archiveSelect.append(''); } - let archiveVal = inputTds.eq(4).children().val(); + var archiveVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(archiveSelect).children().val(archiveVal).chosen({width: "101%"}); } else if ( attr.indexOf('Weekday') >= 0 ) { //Weekday selection - let weekdaySelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); - for (let i = 0; i < weekdays.length; i++) { + var weekdaySelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + for (var i = 0; i < weekdays.length; i++) { weekdaySelect.append(''); } - let weekdayVal = inputTds.eq(4).children().val(); + var weekdayVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(weekdaySelect).children().val(weekdayVal).chosen({width: "101%"}); } else if ( attr == 'StateId' ) { //Run state - let stateSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); - for (let key in states) { + var stateSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + for (var key in states) { stateSelect.append(''); } - let stateVal = inputTds.eq(4).children().val(); + var stateVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(stateSelect).children().val(stateVal).chosen({width: "101%"}); } else if ( attr == 'ServerId' || attr == 'MonitorServerId' || attr == 'StorageServerId' || attr == 'FilterServerId' ) { //Select Server - let serverSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); - for (let key in servers) { + var serverSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + for (var key in servers) { serverSelect.append(''); } - let serverVal = inputTds.eq(4).children().val(); + var serverVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(serverSelect).children().val(serverVal).chosen({width: "101%"}); } else if ( attr == 'StorageId' ) { //Choose by storagearea - let storageSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + var storageSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); for ( key in storageareas ) { storageSelect.append(''); } - let storageVal = inputTds.eq(4).children().val(); + var storageVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(storageSelect).children().val(storageVal).chosen({width: "101%"}); } else if ( attr == 'MonitorName' ) { //Monitor names - let monitorSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); - for (let key in monitors) { + var monitorSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + for (var key in monitors) { monitorSelect.append(''); } - let monitorVal = inputTds.eq(4).children().val(); + var monitorVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(monitorSelect).children().val(monitorVal); } else { //Reset to regular text field and operator for everything that isn't special - let opSelect = $j('').attr('name', queryPrefix + rowNum + '][op]').attr('id', queryPrefix + rowNum + '][op]'); - for (let key in opTypes) { + var opSelect = $j('').attr('name', queryPrefix + rowNum + '][op]').attr('id', queryPrefix + rowNum + '][op]'); + for (var key in opTypes) { opSelect.append(''); } - let opVal = inputTds.eq(3).children().val(); + var opVal = inputTds.eq(3).children().val(); inputTds.eq(3).html(opSelect).children().val(opVal).chosen({width: "101%"}); - let textInput = $j('').attr('type', 'text').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); - let textVal = inputTds.eq(4).children().val(); + var textInput = $j('').attr('type', 'text').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + var textVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(textInput).children().val(textVal); } if ( attr.endsWith('DateTime') ) { //Start/End DateTime @@ -212,7 +212,7 @@ function parseRows (rows) { } attr = inputTds.find("[name$='attr\\]']") // Set attr list id and name - let term = attr.attr('name').split(/[[\]]{1,2}/); + var term = attr.attr('name').split(/[[\]]{1,2}/); term.length--; term.shift(); term[2] = rowNum; @@ -223,7 +223,7 @@ function parseRows (rows) { } function stringFilter (term) { - let termString = ''; + var termString = ''; term.forEach(function(item) { termString += '[' + item + ']'; }); @@ -231,23 +231,23 @@ function stringFilter (term) { } function addTerm( element ) { - let row = $j(element).closest('tr'); + var row = $j(element).closest('tr'); row.find('select').chosen("destroy"); - let newRow = row.clone().insertAfter(row); + var newRow = row.clone().insertAfter(row); row.find('select').chosen({width: "101%"}); newRow.find('select').each( function () { //reset new row to default this[0].selected = 'selected'; }).chosen({width: "101%"}); newRow.find('input[type="text"]').val(''); - let rows = $j(row).parent().children(); + var rows = $j(row).parent().children(); parseRows(rows); } function delTerm( element ) { - let row = $j(element).closest('tr'); - let rowParent = $j(row).parent(); + var row = $j(element).closest('tr'); + var rowParent = $j(row).parent(); row.remove(); - let rows = rowParent.children(); + var rows = rowParent.children(); parseRows(rows); } From f2f1e230d14232e7bc1737d8d109d601e48c2792 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 3 Dec 2018 16:25:03 -0500 Subject: [PATCH 177/240] put back missing ! --- scripts/ZoneMinder/lib/ZoneMinder/Database.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm index dcc797bd4..173c0033c 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm @@ -208,7 +208,7 @@ sub zmDbGetMonitor { return undef; } my $res = $sth->execute($id); - if ( $res ) { + if ( !$res ) { Error("Can't execute '$sql': ".$sth->errstr()); return undef; } From 9ffd77428afe9a2c5a7d7cd2d7d919f28ff222b6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 5 Dec 2018 09:05:10 -0500 Subject: [PATCH 178/240] fix paths to jquery-ui-theme components, thereby upgrading them to the proper version. This fixes the datetime filters not being shown on skins that don't specify a custom theme for jquery-ui --- .../classic/css/base/jquery-ui-theme.css | 410 ------------------ .../classic/css/classic/jquery-ui-theme.css | 410 ------------------ .../classic/css/dark/jquery-ui-theme.css | 410 ------------------ web/skins/classic/includes/functions.php | 8 +- 4 files changed, 4 insertions(+), 1234 deletions(-) delete mode 100644 web/skins/classic/css/base/jquery-ui-theme.css delete mode 100644 web/skins/classic/css/classic/jquery-ui-theme.css delete mode 100644 web/skins/classic/css/dark/jquery-ui-theme.css diff --git a/web/skins/classic/css/base/jquery-ui-theme.css b/web/skins/classic/css/base/jquery-ui-theme.css deleted file mode 100644 index c50986c55..000000000 --- a/web/skins/classic/css/base/jquery-ui-theme.css +++ /dev/null @@ -1,410 +0,0 @@ -/*! - * jQuery UI CSS Framework 1.11.3 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/theming/ - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #dddddd; - background: #ffffff; - color: #333333; -} -.ui-widget-content a { - color: #333333; -} -.ui-widget-header { - border: 1px solid #dddddd; - background: #e9e9e9; - color: #333333; - font-weight: bold; -} -.ui-widget-header a { - color: #333333; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #c5c5c5; - background: #f6f6f6; - font-weight: normal; - color: #454545; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #454545; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #cccccc; - background: #ededed; - font-weight: normal; - color: #2b2b2b; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited { - color: #2b2b2b; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #003eff; - background: #007fff; - font-weight: normal; - color: #ffffff; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #ffffff; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #dad55e; - background: #fffa90; - color: #777620; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #777620; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #f1a899; - background: #fddfdf; - color: #5f3f3f; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #5f3f3f; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #5f3f3f; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_444444_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_444444_256x240.png"); -} -.ui-state-default .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777777_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_555555_256x240.png"); -} -.ui-state-active .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_ffffff_256x240.png"); -} -.ui-state-highlight .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777620_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_cc0000_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 3px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 3px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 3px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 3px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #aaaaaa; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ -} -.ui-widget-shadow { - margin: 0px 0 0 0px; - padding: 5px; - background: #666666; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ - border-radius: 8px; -} diff --git a/web/skins/classic/css/classic/jquery-ui-theme.css b/web/skins/classic/css/classic/jquery-ui-theme.css deleted file mode 100644 index c50986c55..000000000 --- a/web/skins/classic/css/classic/jquery-ui-theme.css +++ /dev/null @@ -1,410 +0,0 @@ -/*! - * jQuery UI CSS Framework 1.11.3 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/theming/ - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #dddddd; - background: #ffffff; - color: #333333; -} -.ui-widget-content a { - color: #333333; -} -.ui-widget-header { - border: 1px solid #dddddd; - background: #e9e9e9; - color: #333333; - font-weight: bold; -} -.ui-widget-header a { - color: #333333; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #c5c5c5; - background: #f6f6f6; - font-weight: normal; - color: #454545; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #454545; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #cccccc; - background: #ededed; - font-weight: normal; - color: #2b2b2b; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited { - color: #2b2b2b; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #003eff; - background: #007fff; - font-weight: normal; - color: #ffffff; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #ffffff; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #dad55e; - background: #fffa90; - color: #777620; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #777620; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #f1a899; - background: #fddfdf; - color: #5f3f3f; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #5f3f3f; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #5f3f3f; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_444444_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_444444_256x240.png"); -} -.ui-state-default .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777777_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_555555_256x240.png"); -} -.ui-state-active .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_ffffff_256x240.png"); -} -.ui-state-highlight .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777620_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_cc0000_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 3px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 3px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 3px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 3px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #aaaaaa; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ -} -.ui-widget-shadow { - margin: 0px 0 0 0px; - padding: 5px; - background: #666666; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ - border-radius: 8px; -} diff --git a/web/skins/classic/css/dark/jquery-ui-theme.css b/web/skins/classic/css/dark/jquery-ui-theme.css deleted file mode 100644 index 6288b262e..000000000 --- a/web/skins/classic/css/dark/jquery-ui-theme.css +++ /dev/null @@ -1,410 +0,0 @@ -/*! - * jQuery UI CSS Framework 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/theming/ - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=2px&bgColorHeader=%23222222&bgTextureHeader=flat&borderColorHeader=%23222222&fcHeader=%23eeeeee&iconColorHeader=%23777777&bgColorContent=%23222222&bgTextureContent=flat&borderColorContent=%23dddddd&fcContent=%23dddddd&iconColorContent=%23444444&bgColorDefault=%23444444&bgTextureDefault=flat&borderColorDefault=%23444444&fcDefault=%23eeeeee&iconColorDefault=%23777777&bgColorHover=%23555555&bgTextureHover=flat&borderColorHover=%23444444&fcHover=%23eeeeee&iconColorHover=%23777777&bgColorActive=%23666666&bgTextureActive=flat&borderColorActive=%23666666&fcActive=%23eeeeee&iconColorActive=%23777777&bgColorHighlight=%23222222&bgTextureHighlight=flat&borderColorHighlight=%23777777&fcHighlight=%23eeeeee&iconColorHighlight=%23777777&bgColorError=%23fddfdf&bgTextureError=flat&borderColorError=%23f1a899&fcError=%235f3f3f&iconColorError=%23cc0000&bgColorOverlay=%23aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=%23666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px&bgImgOpacityHeader=&bgImgOpacityContent=&bgImgOpacityDefault=&bgImgOpacityHover=&bgImgOpacityActive=&bgImgOpacityHighlight=&bgImgOpacityError= - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Arial,Helvetica,sans-serif; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #dddddd; - background: #222222; - color: #dddddd; -} -.ui-widget-content a { - color: #dddddd; -} -.ui-widget-header { - border: 1px solid #222222; - background: #222222; - color: #eeeeee; - font-weight: bold; -} -.ui-widget-header a { - color: #eeeeee; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #444444; - background: #444444; - font-weight: normal; - color: #eeeeee; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #eeeeee; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #444444; - background: #555555; - font-weight: normal; - color: #eeeeee; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited, -.ui-state-focus a, -.ui-state-focus a:hover, -.ui-state-focus a:link, -.ui-state-focus a:visited { - color: #eeeeee; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #666666; - background: #666666; - font-weight: normal; - color: #eeeeee; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #eeeeee; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #777777; - background: #222222; - color: #eeeeee; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #eeeeee; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #f1a899; - background: #fddfdf; - color: #5f3f3f; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #5f3f3f; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #5f3f3f; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); /* support: IE8 */ - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); /* support: IE8 */ - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_444444_256x240.png"); -} -.ui-widget-header .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777777_256x240.png"); -} -.ui-state-default .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777777_256x240.png"); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777777_256x240.png"); -} -.ui-state-active .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777777_256x240.png"); -} -.ui-state-highlight .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_777777_256x240.png"); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("../skins/classic/graphics/ui-icons_cc0000_256x240.png"); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 2px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 2px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 2px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 2px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #aaaaaa; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ -} -.ui-widget-shadow { - margin: 0px 0 0 0px; - padding: 5px; - background: #666666; - opacity: .3; - filter: Alpha(Opacity=30); /* support: IE8 */ - border-radius: 8px; -} diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 50dd19f7c..91ff87073 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -81,10 +81,10 @@ echo output_link_if_exists( array( 'css/'.$css.'/skin.css', 'css/base/views/'.$basename.'.css', 'css/'.$css.'/views/'.$basename.'.css', - '/js/dateTimePicker/jquery-ui-timepicker-addon.css', - '/js/jquery-ui-1.12.1/jquery-ui.structure.min.css', - '/css/jquery-ui-1.12.1/jquery-ui.theme.min.css', - '/css/'.$css.'/jquery-ui-theme.css', + 'js/dateTimePicker/jquery-ui-timepicker-addon.css', + 'js/jquery-ui-1.12.1/jquery-ui.structure.min.css', + 'js/jquery-ui-1.12.1/jquery-ui.theme.min.css', + 'css/'.$css.'/jquery-ui-theme.css', ) ); ?> From 757e5385502474dcfa669a789fb7010bba553f04 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 6 Dec 2018 17:12:03 -0500 Subject: [PATCH 179/240] strip port from HTTP_HOST --- web/includes/Server.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/includes/Server.php b/web/includes/Server.php index dae6cd7c2..502d0efa5 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -52,7 +52,12 @@ class Server { return $this->{'Name'}; } # Use HTTP_HOST instead of SERVER_NAME here for nginx compatiblity - return $_SERVER['HTTP_HOST']; + # ICON: Hi, I just met you, and this is crazy, but I need to strip port. + $host_with_port_maybe = $_SERVER['HTTP_HOST']; + $heres_my_host = preg_replace('/([^:]+)(:\d+)?/','${1}', $host_with_port_maybe); + #Just use it baby + + return $heres_my_host; } public function Protocol( $new = null ) { From a1141d2dc43edd5bd89b79db6241c4258dc0faf2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 7 Dec 2018 08:39:23 -0500 Subject: [PATCH 180/240] remove second use of HTTP_HOST and use a better method of stripping off port from HTTP_HOST --- web/includes/Server.php | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/web/includes/Server.php b/web/includes/Server.php index 502d0efa5..aba82e79e 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -51,13 +51,8 @@ class Server { } else if ( $this->Id() ) { return $this->{'Name'}; } - # Use HTTP_HOST instead of SERVER_NAME here for nginx compatiblity - # ICON: Hi, I just met you, and this is crazy, but I need to strip port. - $host_with_port_maybe = $_SERVER['HTTP_HOST']; - $heres_my_host = preg_replace('/([^:]+)(:\d+)?/','${1}', $host_with_port_maybe); - #Just use it baby - - return $heres_my_host; + $result = explode(':',$_SERVER['HTTP_HOST']); + return $result[0]; } public function Protocol( $new = null ) { @@ -96,12 +91,7 @@ class Server { public function Url( $port = null ) { $url = $this->Protocol().'://'; - if ( $this->Id() ) { - $url .= $this->Hostname(); - } else { - # Use HTTP_HOST instead of SERVER_NAME here for nginx compatiblity - $url .= $_SERVER['HTTP_HOST']; - } + $url .= $this->Hostname(); if ( $port ) { $url .= ':'.$port; } else { From db81465fa24fe666551cb6ab28ad9be3135bb601 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 7 Dec 2018 09:47:00 -0600 Subject: [PATCH 181/240] allow one to set manpage destination --- CMakeLists.txt | 7 ++++++- cmake/Modules/Pod2Man.cmake | 4 ++-- scripts/CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d070c6d3..46f3b0372 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,8 @@ mark_as_advanced( ZM_PATH_ARP ZM_CONFIG_DIR ZM_CONFIG_SUBDIR - ZM_SYSTEMD) + ZM_SYSTEMD + ZM_MANPAGE_DEST_PREFIX) set(ZM_RUNDIR "/var/run/zm" CACHE PATH "Location of transient process files, default: /var/run/zm") @@ -210,6 +211,10 @@ set(ZM_TARGET_DISTRO "" CACHE STRING "Build ZoneMinder for a specific distribution. Currently, valid names are: fc27, fc26, el7, OS13, FreeBSD") set(ZM_SYSTEMD "OFF" CACHE BOOL "Set to ON to force building ZM with systemd support. default: OFF") +set(ZM_MANPAGE_DEST_PREFIX "share/man" CACHE PATH + "Relative path used to install ZoneMinder's Man pages into a + non-standard folder. Most Linux users will not need to change this. + BSD users may need to set this.") # Reassign some variables if a target distro has been specified if((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc")) diff --git a/cmake/Modules/Pod2Man.cmake b/cmake/Modules/Pod2Man.cmake index 6804fab53..f1bc2faf6 100644 --- a/cmake/Modules/Pod2Man.cmake +++ b/cmake/Modules/Pod2Man.cmake @@ -21,7 +21,7 @@ # To use it, include this file in CMakeLists.txt and # invoke POD2MAN(
) -MACRO(POD2MAN PODFILE MANFILE SECTION) +MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX) FIND_PROGRAM(POD2MAN pod2man) FIND_PROGRAM(GZIP gzip) @@ -58,7 +58,7 @@ MACRO(POD2MAN PODFILE MANFILE SECTION) INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz - DESTINATION share/man/man${SECTION} + DESTINATION ${MANPAGE_DEST_PREFIX}/man${SECTION} ) ENDMACRO(POD2MAN PODFILE MANFILE SECTION) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index f1bfa2ed1..3ecded8db 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -31,7 +31,7 @@ configure_file(zm.in "${CMAKE_CURRENT_BINARY_DIR}/zm" @ONLY) file(GLOB perlscripts "*.pl") FOREACH(PERLSCRIPT ${perlscripts}) get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME) - POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8) + POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX}) ENDFOREACH(PERLSCRIPT ${perlscripts}) # Install the perl scripts diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a87abe955..309a2c05f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,7 +21,7 @@ target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS}) # Generate man files for the binaries destined for the bin folder FOREACH(CBINARY zma zmc zmu) - POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8) + POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8 ${ZM_MANPAGE_DEST_PREFIX}) ENDFOREACH(CBINARY zma zmc zmu) install(TARGETS zmc zma zmu RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) From 16318ca3ef876f6baef1211bbb0cf7e71d720097 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 7 Dec 2018 09:59:28 -0600 Subject: [PATCH 182/240] Update zoneminder.spec --- distros/redhat/zoneminder.spec | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 734a70a25..d42fa6477 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -42,7 +42,7 @@ BuildRequires: systemd-devel BuildRequires: mariadb-devel BuildRequires: perl-podlators BuildRequires: polkit-devel -BuildRequires: cmake >= 2.8.7 +BuildRequires: cmake3 BuildRequires: gnutls-devel BuildRequires: bzip2-devel BuildRequires: pcre-devel @@ -200,7 +200,7 @@ mv -f CakePHP-Enum-Behavior-%{ceb_version} ./web/api/app/Plugin/CakePHP-Enum-Beh ./utils/zmeditconfigdata.sh ZM_OPT_FAST_DELETE no %build -%cmake \ +%cmake3 \ -DZM_WEB_USER="%{zmuid_final}" \ -DZM_WEB_GROUP="%{zmgid_final}" \ -DZM_TARGET_DISTRO="%{zmtargetdistro}" \ @@ -411,9 +411,14 @@ EOF %dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload %changelog -* Wed Nov 14 2018 Andrew Bauer - 1.32.2-2 +* Fri Dec 07 2018 Andrew Bauer - 1.32.3-1 +- 1.32.3 Release - Break into sub-packages +* Tue Nov 13 2018 Antonio Trande - 1.32.2-2 +- Rebuild for ffmpeg-3.4.5 on el7 +- Use CMake3 + * Sat Oct 13 2018 Andrew Bauer - 1.32.2-1 - 1.32.2 release - Bug fix release From c3620672b308934eedc72a9e798e6879ec0e0a45 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 8 Dec 2018 08:19:55 -0600 Subject: [PATCH 183/240] 1.32.3 release --- distros/redhat/zoneminder.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index d42fa6477..941bad900 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -23,8 +23,8 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.32.2 -Release: 2%{?dist} +Version: 1.32.3 +Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons # Mootools is inder the MIT license: http://mootools.net/ @@ -411,7 +411,7 @@ EOF %dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload %changelog -* Fri Dec 07 2018 Andrew Bauer - 1.32.3-1 +* Sat Dec 08 2018 Andrew Bauer - 1.32.3-1 - 1.32.3 Release - Break into sub-packages From 077c643da0975a75a46255d5be1a1a2aeae62069 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 8 Dec 2018 08:22:36 -0600 Subject: [PATCH 184/240] 1.32.3 release --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index c78d39b8e..00b225209 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.32.2 +1.32.3 From 08899b69c33e7d6663f35e0d0761bcb8af4faf00 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 8 Dec 2018 12:04:57 -0600 Subject: [PATCH 185/240] update ENDMACRO --- cmake/Modules/Pod2Man.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Modules/Pod2Man.cmake b/cmake/Modules/Pod2Man.cmake index f1bc2faf6..734be239b 100644 --- a/cmake/Modules/Pod2Man.cmake +++ b/cmake/Modules/Pod2Man.cmake @@ -60,7 +60,7 @@ MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX) FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz DESTINATION ${MANPAGE_DEST_PREFIX}/man${SECTION} ) -ENDMACRO(POD2MAN PODFILE MANFILE SECTION) +ENDMACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX) MACRO(ADD_MANPAGE_TARGET) # It is not possible add a dependency to target 'install' From 1e8c4276bb86ec480e7ea1564c8a49b9fac53112 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 10 Dec 2018 17:32:17 -0500 Subject: [PATCH 186/240] fix #2319 some more. This is fixing rate sticking across gapless events and reload --- web/skins/classic/views/js/event.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 9981b1458..37de97f69 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -275,7 +275,8 @@ function pauseClicked() { } function vjsPause() { - stopFastRev(); + if ( intervalRewind ) + stopFastRev(); streamPause(); } @@ -307,7 +308,7 @@ function vjsPlay() { //catches if we change mode programatically if ( intervalRewind ) stopFastRev(); $j('#rateValue').html(vid.playbackRate()); - Cookie.write('zmEventRate', vid.playbackRate(), {duration: 10*365}); + Cookie.write('zmEventRate', vid.playbackRate()*100, {duration: 10*365}); streamPlay(); } @@ -575,7 +576,7 @@ function getEventResponse( respObj, respText ) { drawProgressBar(); } nearEventsQuery( eventData.Id ); -} +} // end function getEventResponse var eventReq = new Request.JSON( { url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getEventResponse } ); From e1ecd47bffdc15a34d54a748938ac6af5c48812b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Dec 2018 09:40:40 -0500 Subject: [PATCH 187/240] Fix missing use of UrlToApi --- 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 c1a6a47df..cc1d8eed7 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -451,7 +451,7 @@ private $control_fields = array( } else if ( $this->ServerId() ) { $Server = $this->Server(); - $url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/'.$this->{'Id'}.'.json'; + $url = $Server->UrlToApi().'/monitors/'.$this->{'Id'}.'.json'; if ( ZM_OPT_USE_AUTH ) { if ( ZM_AUTH_RELAY == 'hashed' ) { $url .= '?auth='.generateAuthHash( ZM_AUTH_HASH_IPS ); From b3bed9a28ab6190120603dc041a52efbab7a67f8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Dec 2018 10:20:02 -0500 Subject: [PATCH 188/240] fix whitespace --- web/api/app/Model/Event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/api/app/Model/Event.php b/web/api/app/Model/Event.php index a59393d9a..14dbd377e 100644 --- a/web/api/app/Model/Event.php +++ b/web/api/app/Model/Event.php @@ -100,7 +100,7 @@ class Event extends AppModel { ), ); - public function Relative_Path($event) { + public function Relative_Path($event) { $event_path = ''; if ( $event['Scheme'] == 'Deep' ) { From af6b709ae1d05c7d07126dc8fdfe21b0f6ada221 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 11 Dec 2018 09:28:48 -0600 Subject: [PATCH 189/240] bump to 1.33.0 development --- db/zm_update-1.33.0.sql | 6 ++++++ distros/redhat/zoneminder.spec | 5 ++++- version | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 db/zm_update-1.33.0.sql diff --git a/db/zm_update-1.33.0.sql b/db/zm_update-1.33.0.sql new file mode 100644 index 000000000..ebf6573a7 --- /dev/null +++ b/db/zm_update-1.33.0.sql @@ -0,0 +1,6 @@ +-- +-- This updates a 1.32.3 database to 1.33.0 +-- +-- No changes required +-- + diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 941bad900..cbda079ca 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -23,7 +23,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.32.3 +Version: 1.33.0 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons @@ -411,6 +411,9 @@ EOF %dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload %changelog +* Tue Dec 11 2018 Andrew Bauer - 1.33.0-1 +- Bump tp 1.33.0 Development + * Sat Dec 08 2018 Andrew Bauer - 1.32.3-1 - 1.32.3 Release - Break into sub-packages diff --git a/version b/version index 00b225209..7aa332e41 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.32.3 +1.33.0 From 4e4c7502c3a6f206009dfeb5e8c610dd4afcbd8d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Dec 2018 10:37:52 -0500 Subject: [PATCH 190/240] put sql update into zm_update-1.33.0.sql --- db/zm_update-1.33.0.sql | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 db/zm_update-1.33.0.sql diff --git a/db/zm_update-1.33.0.sql b/db/zm_update-1.33.0.sql new file mode 100644 index 000000000..2e2d227e1 --- /dev/null +++ b/db/zm_update-1.33.0.sql @@ -0,0 +1,18 @@ +-- +-- This updates a 1.32.* database to 1.33.0 +-- +-- Remove DefaultView from Monitors table. + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Monitors' + AND table_schema = DATABASE() + AND column_name = 'DefaultView' + ) > 0, +"ALTER TABLE Monitors DROP COLUMN DefaultView" +"SELECT 'Column DefaultView no longer exists in Monitors'", +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; From c4bf67b06371a2510d083c8b7e1bc81b9df4b7b1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 12 Dec 2018 09:17:14 -0500 Subject: [PATCH 191/240] fix commas --- db/zm_update-1.33.0.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/zm_update-1.33.0.sql b/db/zm_update-1.33.0.sql index 624d254eb..cc7a257c7 100644 --- a/db/zm_update-1.33.0.sql +++ b/db/zm_update-1.33.0.sql @@ -12,8 +12,8 @@ SET @s = (SELECT IF( AND table_schema = DATABASE() AND column_name = 'DefaultView' ) > 0, -"ALTER TABLE Monitors DROP COLUMN DefaultView" -"SELECT 'Column DefaultView no longer exists in Monitors'", +"ALTER TABLE Monitors DROP COLUMN DefaultView", +"SELECT 'Column DefaultView no longer exists in Monitors'" )); PREPARE stmt FROM @s; From 882c4e2ea66435c7cca8161c7b7827df4326b6ce Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 12 Dec 2018 20:55:50 -0600 Subject: [PATCH 192/240] Update zm_update-1.33.0.sql fixes #2342 --- db/zm_update-1.33.0.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/zm_update-1.33.0.sql b/db/zm_update-1.33.0.sql index 624d254eb..cc7a257c7 100644 --- a/db/zm_update-1.33.0.sql +++ b/db/zm_update-1.33.0.sql @@ -12,8 +12,8 @@ SET @s = (SELECT IF( AND table_schema = DATABASE() AND column_name = 'DefaultView' ) > 0, -"ALTER TABLE Monitors DROP COLUMN DefaultView" -"SELECT 'Column DefaultView no longer exists in Monitors'", +"ALTER TABLE Monitors DROP COLUMN DefaultView", +"SELECT 'Column DefaultView no longer exists in Monitors'" )); PREPARE stmt FROM @s; From 567b60ffa76b60b244a8731090521b58fb070779 Mon Sep 17 00:00:00 2001 From: Mike Rosack Date: Thu, 13 Dec 2018 09:24:32 -0600 Subject: [PATCH 193/240] support for forwarded proto/port in Server.php (#2343) --- web/includes/Server.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/web/includes/Server.php b/web/includes/Server.php index aba82e79e..7424aafdf 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -62,7 +62,12 @@ class Server { if ( isset($this->{'Protocol'}) and ( $this->{'Protocol'} != '' ) ) { return $this->{'Protocol'}; } - return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http'; + + return ( + ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ) + or + ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and ( $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) ) + ) ? 'https' : 'http'; } public function Port( $new = '' ) { @@ -72,6 +77,11 @@ class Server { if ( isset($this->{'Port'}) and $this->{'Port'} ) { return $this->{'Port'}; } + + if ( isset($_SERVER['HTTP_X_FORWARDED_PORT']) ) { + return $_SERVER['HTTP_X_FORWARDED_PORT']; + } + return $_SERVER['SERVER_PORT']; } From 0784a8a5a17872fe1de683b5ec98c9cbf8b218cf Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 13 Dec 2018 10:27:44 -0500 Subject: [PATCH 194/240] reduce ffmpeg log levels from error to warning and warning to info. Ffmpeg outputs a lot of errors that don't significantly affect video recording. --- src/zm_ffmpeg.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index d0bac6464..cc4565fbe 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -34,9 +34,11 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs ) } else if ( level == AV_LOG_FATAL ) { // 8 log_level = Logger::FATAL; } else if ( level == AV_LOG_ERROR ) { // 16 - log_level = Logger::ERROR; + log_level = Logger::WARNING; // ffmpeg outputs a lot of errors that don't really affect anything. + //log_level = Logger::ERROR; } else if ( level == AV_LOG_WARNING ) { //24 - log_level = Logger::WARNING; + log_level = Logger::INFO; + //log_level = Logger::WARNING; } else if ( level == AV_LOG_INFO ) { //32 log_level = Logger::INFO; } else if ( level == AV_LOG_VERBOSE ) { //40 From a1e9058729eaa33e085a155a1b850bb50812933c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 13 Dec 2018 16:19:55 -0500 Subject: [PATCH 195/240] adjust ffmpeg logging levels --- src/zm_ffmpeg.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index cc4565fbe..3e25cee40 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -40,11 +40,12 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs ) log_level = Logger::INFO; //log_level = Logger::WARNING; } else if ( level == AV_LOG_INFO ) { //32 - log_level = Logger::INFO; - } else if ( level == AV_LOG_VERBOSE ) { //40 log_level = Logger::DEBUG1; - } else if ( level == AV_LOG_DEBUG ) { //48 + //log_level = Logger::INFO; + } else if ( level == AV_LOG_VERBOSE ) { //40 log_level = Logger::DEBUG2; + } else if ( level == AV_LOG_DEBUG ) { //48 + log_level = Logger::DEBUG3; #ifdef AV_LOG_TRACE } else if ( level == AV_LOG_TRACE ) { log_level = Logger::DEBUG8; From 3a081785002daf8df939aa36bef06fac5b1e285a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 13 Dec 2018 19:00:46 -0600 Subject: [PATCH 196/240] Create support.yml --- .github/support.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/support.yml diff --git a/.github/support.yml b/.github/support.yml new file mode 100644 index 000000000..fc61e151e --- /dev/null +++ b/.github/support.yml @@ -0,0 +1,27 @@ +# Configuration for support-requests - https://github.com/dessant/support-requests + +# Label used to mark issues as support requests +supportLabel: support + +# Comment to post on issues marked as support requests, `{issue-author}` is an +# optional placeholder. Set to `false` to disable +supportComment: > + :wave: @{issue-author}, we use the issue tracker exclusively for bug reports. + However, this issue appears to be a support request, a feature request, or + attempts to ask a question. + + Please use our support channels to get help with or discuss this project: + - The [ZoneMinder-Chat Slack channel](https://zoneminder-chat.herokuapp.com/) + - The [ZoneMinder Forum](https://forums.zoneminder.com/) + +# Close issues marked as support requests +close: true + +# Lock issues marked as support requests +lock: true + +# Assign `off-topic` as the reason for locking. Set to `false` to disable +setLockReason: true + +# Repository to extend settings from +# _extends: repo From ebaafef607a626f96043ad0b9450d6ff7df35be3 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Fri, 14 Dec 2018 08:01:23 -0500 Subject: [PATCH 197/240] Ffmpeg logs optional (#2345) * make ffmpeg logs configurable via web * fix Info --- scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in | 14 ++++++++++++++ src/zm_ffmpeg.cpp | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index eac13cb75..27d993894 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -1202,6 +1202,20 @@ our @options = ( category => 'logging', }, { + name => 'ZM_LOG_FFMPEG', + default => 'yes', + description => 'Log FFMPEG messages', + help => q` + When enabled (default is on), this option will log FFMPEG messages. + FFMPEG messages can be useful when debugging streaming issues. However, + depending on your distro and FFMPEG version, this may also result in + more logs than you'd typically like to see. If all your streams are working + well, you may choose to turn this off. + `, + type => $types{boolean}, + category => 'logging', + }, +{ name => 'ZM_LOG_DEBUG', default => 'no', description => 'Switch debugging on', diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 3e25cee40..eb95e3659 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -73,7 +73,10 @@ void FFMPEGInit() { av_log_set_level( AV_LOG_DEBUG ); else av_log_set_level( AV_LOG_QUIET ); - av_log_set_callback(log_libav_callback); + if ( config.log_ffmpeg ) + av_log_set_callback(log_libav_callback); + else + Info("Not enabling ffmpeg logs, as LOG_FFMPEG is disabled in options"); av_register_all(); avformat_network_init(); bInit = true; From 70388753eac08c813a918ce643f0240bb6c967dc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Dec 2018 08:39:55 -0500 Subject: [PATCH 198/240] COmment out logging in signal handlers. Logging is too complex. --- src/zm_signal.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zm_signal.cpp b/src/zm_signal.cpp index 034ff7d66..e13bfdc9c 100644 --- a/src/zm_signal.cpp +++ b/src/zm_signal.cpp @@ -31,13 +31,15 @@ bool zm_terminate = false; RETSIGTYPE zm_hup_handler(int signal) { - Info("Got signal %d (%s), reloading", signal, strsignal(signal)); + // Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes. + //Info("Got signal %d (%s), reloading", signal, strsignal(signal)); zm_reload = true; } RETSIGTYPE zm_term_handler(int signal) { - Info("Got signal %d (%s), exiting", signal, strsignal(signal)); + // Shouldn't do complex things in signal handlers, logging is complex and can block due to mutexes. + //Info("Got signal %d (%s), exiting", signal, strsignal(signal)); zm_terminate = true; } From 1a05e777c03502206ffb4615d31427716242163c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Dec 2018 08:54:29 -0500 Subject: [PATCH 199/240] fix path not being constructed properly for shallow event storage --- src/zm_event.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 4eac38911..ed8a08a6f 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -175,7 +175,7 @@ Event::Event( Error("Can't mkdir %s: %s", path, strerror(errno)); } } else { - snprintf(path, sizeof(path), "/%" PRIu64, id); + path_ptr += snprintf(path_ptr, sizeof(path), "/%" PRIu64, id); if ( mkdir(path, 0755) ) { if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); From ad4f1312840c2e13e9e877bd81ca15e41d18c01c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Dec 2018 12:22:10 -0500 Subject: [PATCH 200/240] Must unlock before logging --- src/zm_event.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index ed8a08a6f..6b244a005 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -252,11 +252,12 @@ Event::~Event() { id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec); db_mutex.lock(); if ( mysql_query(&dbconn, sql) ) { + db_mutex.unlock(); Error("Can't insert frame: %s", mysql_error(&dbconn)); } else { + db_mutex.unlock(); Debug(1,"Success writing last frame"); } - db_mutex.unlock(); } snprintf(sql, sizeof(sql), @@ -264,8 +265,8 @@ Event::~Event() { monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, video_name, id ); db_mutex.lock(); while ( mysql_query(&dbconn, sql) && !zm_terminate ) { - Error("Can't update event: %s reason: %s", sql, mysql_error(&dbconn)); db_mutex.unlock(); + Error("Can't update event: %s reason: %s", sql, mysql_error(&dbconn)); sleep(1); db_mutex.lock(); } From 5a6e700c456176fe2eedc4065caaf9725caae00a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 14 Dec 2018 20:27:12 -0600 Subject: [PATCH 201/240] rpm packaging - update fcgiwrap socket location I pushed a new fgciwrap package to Fedora and the socket file in the package is in a different location. See: https://bugzilla.redhat.com/show_bug.cgi?id=1655281 --- distros/redhat/nginx/zoneminder.nginx.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distros/redhat/nginx/zoneminder.nginx.conf.in b/distros/redhat/nginx/zoneminder.nginx.conf.in index c2e3edee7..2976a83b2 100644 --- a/distros/redhat/nginx/zoneminder.nginx.conf.in +++ b/distros/redhat/nginx/zoneminder.nginx.conf.in @@ -21,7 +21,7 @@ server { include /etc/nginx/fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; - fastcgi_pass unix:/run/fcgiwrap.sock; + fastcgi_pass unix:/run/fcgiwrap/fcgiwrap-nginx.sock; } location /zm/cache { From c1f46a9cb03bad6efc5ad24e6911b953dfdd9eab Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 15 Dec 2018 16:29:44 -0600 Subject: [PATCH 202/240] Update README.httpd --- distros/redhat/readme/README.httpd | 5 ----- 1 file changed, 5 deletions(-) diff --git a/distros/redhat/readme/README.httpd b/distros/redhat/readme/README.httpd index cb5805b18..5301850df 100644 --- a/distros/redhat/readme/README.httpd +++ b/distros/redhat/readme/README.httpd @@ -146,13 +146,8 @@ Upgrades See step 6 of the installation section if you have not already done this during a previous upgrade. -<<<<<<< HEAD - If this step is not performed correctly, the web console will appear - mostly empty and/or significantly corrupted post-upgrade. -======= IMPORTANT: Failure to complete this step properly will result in a mostly empty or significantly corrupted web console post-upgrade. ->>>>>>> 5b211d250910918782d20bf32b0e33a38a0df4dd 4. Upgrade the database before starting ZoneMinder. From 622c17f628acbe11c58341a5bcf5af5ce2a728f5 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Sun, 16 Dec 2018 11:02:07 -0500 Subject: [PATCH 203/240] make sure auth is regenerated each time we call this API (#2347) --- web/api/app/Controller/HostController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php index d4e19fd77..ce101c73d 100644 --- a/web/api/app/Controller/HostController.php +++ b/web/api/app/Controller/HostController.php @@ -71,7 +71,8 @@ class HostController extends AppController { $zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value']; if ( $zmAuthRelay == 'hashed' ) { $zmAuthHashIps = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_HASH_IPS')))['Config']['Value']; - $credentials = 'auth='.generateAuthHash($zmAuthHashIps); + // make sure auth is regenerated each time we call this API + $credentials = 'auth='.generateAuthHash($zmAuthHashIps,true); } else { // user will need to append the store password here $credentials = 'user='.$this->Session->read('user.Username').'&pass='; From 1d371b7a177c1dcb9ecceb11d9d2190e1904ff7d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 13:41:57 -0500 Subject: [PATCH 204/240] Fix small memleak of linked_monitors not getting freed on Monitor destruction. Fix unlocking db mutex before logging --- src/zm_monitor.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 9f2d92102..5a513dbf8 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -626,6 +626,13 @@ Debug(3, "Success connecting"); } Monitor::~Monitor() { + if ( n_linked_monitors ) { + for( int i = 0; i < n_linked_monitors; i++ ) { + delete linked_monitors[i]; + } + delete[] linked_monitors; + linked_monitors = 0; + } if ( timestamps ) { delete[] timestamps; timestamps = 0; @@ -1906,15 +1913,15 @@ void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) { static char sql[ZM_SQL_SML_BUFSIZ]; snprintf(sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] ); if ( mysql_query(&dbconn, sql) ) { - Error("Can't run query: %s", mysql_error(&dbconn)); db_mutex.unlock(); + Error("Can't run query: %s", mysql_error(&dbconn)); continue; } MYSQL_RES *result = mysql_store_result(&dbconn); if ( !result ) { - Error("Can't use query result: %s", mysql_error(&dbconn)); db_mutex.unlock(); + Error("Can't use query result: %s", mysql_error(&dbconn)); continue; } db_mutex.unlock(); From eccfdb8a6a87e0fd487d14a051ec2450be1032ea Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 13:50:07 -0500 Subject: [PATCH 205/240] Logging and whitespace changes. No logical changes --- .../lib/ZoneMinder/Memory/Mapped.pm | 101 ++++++++---------- 1 file changed, 45 insertions(+), 56 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm index d782c6c9a..b9a8b6a1c 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm @@ -75,55 +75,50 @@ sub zmMemKey { sub zmMemAttach { my ( $monitor, $size ) = @_; - if ( ! $size ) { - Error( "No size passed to zmMemAttach for monitor $$monitor{Id}\n" ); + + if ( !$size ) { + Error("No size passed to zmMemAttach for monitor $$monitor{Id}"); return undef; } - if ( !defined($monitor->{MMapAddr}) ) { - - my $mmap_file = $Config{ZM_PATH_MAP}.'/zm.mmap.'.$monitor->{Id}; - if ( ! -e $mmap_file ) { - Error( sprintf( "Memory map file '%s' does not exist. zmc might not be running." - , $mmap_file - ) - ); - return undef; - } - my $mmap_file_size = -s $mmap_file; - - if ( $mmap_file_size < $size ) { - Error( sprintf( "Memory map file '%s' should have been %d but was instead %d" - , $mmap_file - , $size - , $mmap_file_size - ) - ); - return undef; - } - my $MMAP; - if ( !open( $MMAP, '+<', $mmap_file ) ) { - Error( sprintf( "Can't open memory map file '%s': $!", $mmap_file ) ); - return undef; - } - my $mmap = undef; - my $mmap_addr = mmap( $mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, $MMAP ); - if ( !$mmap_addr || !$mmap ) { - Error( sprintf( "Can't mmap to file '%s': $!\n", $mmap_file ) ); - close( $MMAP ); - return undef; - } - $monitor->{MMapHandle} = $MMAP; - $monitor->{MMapAddr} = $mmap_addr; - $monitor->{MMap} = \$mmap; + if ( defined($monitor->{MMapAddr}) ) { + Debug("zmMemAttach already attached at $monitor->{MMapAddr}"); + return !undef; } + + my $mmap_file = $Config{ZM_PATH_MAP}.'/zm.mmap.'.$monitor->{Id}; + if ( ! -e $mmap_file ) { + Error("Memory map file '$mmap_file' does not exist. zmc might not be running."); + return undef; + } + my $mmap_file_size = -s $mmap_file; + + if ( $mmap_file_size < $size ) { + Error("Memory map file '$mmap_file' should have been $size but was instead $mmap_file_size"); + return undef; + } + my $MMAP; + if ( !open($MMAP, '+<', $mmap_file) ) { + Error("Can't open memory map file '$mmap_file': $!"); + return undef; + } + my $mmap = undef; + my $mmap_addr = mmap($mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, $MMAP); + if ( !$mmap_addr || !$mmap ) { + Error("Can't mmap to file '$mmap_file': $!"); + close($MMAP); + return undef; + } + $monitor->{MMapHandle} = $MMAP; + $monitor->{MMapAddr} = $mmap_addr; + $monitor->{MMap} = \$mmap; return !undef; -} +} # end sub zmMemAttach sub zmMemDetach { my $monitor = shift; if ( $monitor->{MMap} ) { - if ( ! munmap( ${$monitor->{MMap}} ) ) { + if ( ! munmap(${$monitor->{MMap}}) ) { Warn( "Unable to munmap for monitor $$monitor{Id}\n"); } delete $monitor->{MMap}; @@ -132,7 +127,7 @@ sub zmMemDetach { delete $monitor->{MMapAddr}; } if ( $monitor->{MMapHandle} ) { - close( $monitor->{MMapHandle} ); + close($monitor->{MMapHandle}); delete $monitor->{MMapHandle}; } } @@ -144,13 +139,10 @@ sub zmMemGet { my $mmap = $monitor->{MMap}; if ( !$mmap || !$$mmap ) { - Error( sprintf( "Can't read from mapped memory for monitor '%d', gone away?" - , $monitor->{Id} - ) - ); + Error("Can't read from mapped memory for monitor '$$monitor{Id}', gone away?"); return undef; } - my $data = substr( $$mmap, $offset, $size ); + my $data = substr($$mmap, $offset, $size); return $data; } @@ -162,23 +154,20 @@ sub zmMemPut { my $mmap = $monitor->{MMap}; if ( !$mmap || !$$mmap ) { - Error( sprintf( "Can't write mapped memory for monitor '%d', gone away?" - , $monitor->{Id} - ) - ); - return( undef ); + Error("Can't write mapped memory for monitor '$$monitor{Id}', gone away?"); + return undef; } - substr( $$mmap, $offset, $size ) = $data; - return( !undef ); + substr($$mmap, $offset, $size) = $data; + return !undef; } sub zmMemClean { - Debug( "Removing memory map files\n" ); + Debug("Removing memory map files"); my $mapPath = $Config{ZM_PATH_MAP}.'/zm.mmap.*'; foreach my $mapFile( glob( $mapPath ) ) { ( $mapFile ) = $mapFile =~ /^(.+)$/; - Debug( "Removing memory map file '$mapFile'\n" ); - unlink( $mapFile ); + Debug("Removing memory map file '$mapFile'"); + unlink($mapFile); } } From 64bdf40e8631ad5d8bd932d0d64bfbb0cfbf9960 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 13:50:55 -0500 Subject: [PATCH 206/240] Logging and whitespace changes. No logical changes --- .../ZoneMinder/lib/ZoneMinder/Memory.pm.in | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in index 205494791..c04a66c42 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -246,11 +246,12 @@ sub zmMemInit { sub zmMemVerify { my $monitor = shift; - if ( !zmMemAttach( $monitor, $mem_size ) ) { - return( undef ); + + if ( !zmMemAttach($monitor, $mem_size) ) { + return undef; } - my $sd_size = zmMemRead( $monitor, 'shared_data:size', 1 ); + my $sd_size = zmMemRead($monitor, 'shared_data:size', 1); if ( $sd_size != $mem_data->{shared_data}->{size} ) { if ( $sd_size ) { Error( "Shared data size conflict in shared_data for monitor " @@ -268,9 +269,9 @@ sub zmMemVerify { .", got ".$sd_size ); } - return( undef ); + return undef; } - my $td_size = zmMemRead( $monitor, 'trigger_data:size', 1 ); + my $td_size = zmMemRead($monitor, 'trigger_data:size', 1); if ( $td_size != $mem_data->{trigger_data}->{size} ) { if ( $td_size ) { Error( "Shared data size conflict in trigger_data for monitor " @@ -289,14 +290,17 @@ sub zmMemVerify { .$td_size ); } - return( undef ); + return undef; } - if ( !zmMemRead($monitor, 'shared_data:valid',1) ) { - Error( "Shared data not valid for monitor $$monitor{Id}" ); - return( undef ); + my $valid = zmMemRead($monitor, 'shared_data:valid',1); + if ( !$valid ) { + Error("Shared data not valid for monitor $$monitor{Id}"); + return undef; + } else { + Debug("Shared data appears vaild for monitor $$monitor{Id}: $valid"); } - return( !undef ); + return !undef; } sub zmMemRead { From 6af8f0d419a2ab1933d914582d1046e247254b08 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 13:55:18 -0500 Subject: [PATCH 207/240] Logging and whitespace --- scripts/zmdc.pl.in | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in index 4b32b3a65..67bbc294b 100644 --- a/scripts/zmdc.pl.in +++ b/scripts/zmdc.pl.in @@ -257,6 +257,8 @@ sub run { } my $fd = 0; + + # This also closes dbh and CLIENT and SERVER while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) { POSIX::close($fd++); } @@ -300,16 +302,17 @@ sub run { if ( $Config{ZM_SERVER_ID} ) { if ( ! ( $secs_count % 60 ) ) { - Debug("Connecting"); while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) { Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting'); $dbh = zmDbConnect(); } + last if $zm_terminate; + my @cpuload = CpuLoad(); Debug("Updating Server record @cpuload"); if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,CpuLoad=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef, 'Running', $cpuload[0], &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) { - Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID}".$dbh->errstr()); + Error("Failed Updating status of Server record for Id=$Config{ZM_SERVER_ID} :".$dbh->errstr()); } } $secs_count += 1; @@ -375,7 +378,7 @@ sub run { } # end while dPrint(ZoneMinder::Logger::INFO, 'Server exiting at ' - .strftime( '%y/%m/%d %H:%M:%S', localtime() ) + .strftime('%y/%m/%d %H:%M:%S', localtime()) ."\n" ); if ( $Config{ZM_SERVER_ID} ) { @@ -709,7 +712,7 @@ sub reaper { $process->{delay} = $Config{ZM_MAX_RESTART_DELAY}; } } - Debug("Delay for $$process{command} is now $$process{delay}"); + #Debug("Delay for $$process{command} is now $$process{delay}"); } else { delete $cmd_hash{$$process{command}}; } From 88e148068e96f97ce7e33fa475958aa15ef00bdc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 13:56:57 -0500 Subject: [PATCH 208/240] Logging and whitespace --- scripts/zmtrigger.pl.in | 67 +++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index b16e1cdd4..8e1257db9 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -311,7 +311,7 @@ while( 1 ) { # zmDbConnect will ping and reconnect if neccessary $dbh = zmDbConnect(); } # end while ( 1 ) -Info( "Trigger daemon exiting" ); +Info('Trigger daemon exiting'); exit; sub loadMonitor { @@ -327,7 +327,7 @@ sub loadMonitor { } sub loadMonitors { - Debug( "Loading monitors" ); + Debug('Loading monitors'); $monitor_reload_time = time(); my %new_monitors = (); @@ -362,25 +362,25 @@ sub handleMessage { my $monitor = $monitors{$id}; if ( !$monitor ) { - Warning( "Can't find monitor '$id' for message '$message'" ); + Warning("Can't find monitor '$id' for message '$message'"); return; } - Debug( "Found monitor for id '$id'" ); + Debug("Found monitor for id '$id'"); - next if ( !zmMemVerify( $monitor ) ); + next if ( !zmMemVerify($monitor) ); - Debug( "Handling action '$action'" ); + Debug("Handling action '$action'"); if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) { my $state = $1; my $delay = $2; if ( $state eq 'enable' ) { - zmMonitorEnable( $monitor ); + zmMonitorEnable($monitor); } else { - zmMonitorDisable( $monitor ); + zmMonitorDisable($monitor); } # Force a reload $monitor_reload_time = 0; - Info( "Set monitor to $state" ); + Info("Set monitor to $state"); if ( $delay ) { my $action_text = $id.'|'.( ($state eq 'enable') ? 'disable' @@ -395,9 +395,9 @@ sub handleMessage { my $delay = $2; my $trigger_data; if ( $trigger eq 'on' ) { - zmTriggerEventOn( $monitor, $score, $cause, $text ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger' '$cause'" ); + zmTriggerEventOn($monitor, $score, $cause, $text); + zmTriggerShowtext($monitor, $showtext) if defined($showtext); + Info("Trigger '$trigger' '$cause'"); if ( $delay ) { my $action_text = $id.'|cancel'; handleDelay($delay, $connection, $action_text); @@ -407,29 +407,29 @@ sub handleMessage { my $action_text = $id.'|off|0|'.$cause.'|'.$text; handleDelay($delay, $connection, $action_text); } else { - my $last_event = zmGetLastEvent( $monitor ); - zmTriggerEventOff( $monitor ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger'" ); + my $last_event = zmGetLastEvent($monitor); + zmTriggerEventOff($monitor); + zmTriggerShowtext($monitor, $showtext) if defined($showtext); + Info("Trigger '$trigger'"); # Wait til it's finished - while( zmInAlarm( $monitor ) - && ($last_event == zmGetLastEvent( $monitor )) + while( zmInAlarm($monitor) + && ($last_event == zmGetLastEvent($monitor)) ) { # Tenth of a second - usleep( 100000 ); + usleep(100000); } - zmTriggerEventCancel( $monitor ); + zmTriggerEventCancel($monitor); } } # end if trigger is on or off } elsif( $action eq 'cancel' ) { - zmTriggerEventCancel( $monitor ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Cancelled event" ); + zmTriggerEventCancel($monitor); + zmTriggerShowtext($monitor, $showtext) if defined($showtext); + Info('Cancelled event'); } elsif( $action eq 'show' ) { zmTriggerShowtext( $monitor, $showtext ); - Info( "Updated show text to '$showtext'" ); + Info("Updated show text to '$showtext'"); } else { - Error( "Unrecognised action '$action' in message '$message'" ); + Error("Unrecognised action '$action' in message '$message'"); } } # end sub handleMessage @@ -444,8 +444,9 @@ sub handleDelay { $action_array = $actions{$action_time} = []; } push( @$action_array, { connection=>$connection, message=>$action_text } ); - Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)" ); + Debug("Added timed event '$action_text', expires at $action_time (+$delay secs)"); } + 1; __END__ @@ -520,13 +521,13 @@ B|B|B|B|B|B =back -Note that multiple messages can be sent at once and should be LF or CRLF -delimited. This script is not necessarily intended to be a solution in -itself, but is intended to be used as 'glue' to help ZoneMinder interface -with other systems. It will almost certainly require some customisation -before you can make any use of it. If all you want to do is generate alarms -from external sources then using the ZoneMinder::SharedMem perl module is -likely to be easier. + Note that multiple messages can be sent at once and should be LF or CRLF + delimited. This script is not necessarily intended to be a solution in + itself, but is intended to be used as 'glue' to help ZoneMinder interface + with other systems. It will almost certainly require some customisation + before you can make any use of it. If all you want to do is generate alarms + from external sources then using the ZoneMinder::SharedMem perl module is + likely to be easier. =head1 EXAMPLES From 6ee72aa2d98e516c26d00b735a8510aad505661d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 14:06:56 -0500 Subject: [PATCH 209/240] Implement libswresample support as an alternative to libavresample, which is deprecated --- CMakeLists.txt | 50 ++++++++++----- distros/ubuntu1604/control | 5 +- src/zm_videostore.cpp | 125 ++++++++++++++++++++++++------------- src/zm_videostore.h | 12 +++- zoneminder-config.cmake | 2 + 5 files changed, 133 insertions(+), 61 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 46f3b0372..a0d037099 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -607,22 +607,40 @@ if(NOT ZM_NO_FFMPEG) set(optlibsnotfound "${optlibsnotfound} SWScale") endif(SWSCALE_LIBRARIES) - # rescale (using find_library and find_path) - find_library(AVRESAMPLE_LIBRARIES avresample) - if(AVRESAMPLE_LIBRARIES) - set(HAVE_LIBAVRESAMPLE 1) - list(APPEND ZM_BIN_LIBS "${AVRESAMPLE_LIBRARIES}") - find_path(AVRESAMPLE_INCLUDE_DIR "libavresample/avresample.h" /usr/include/ffmpeg) - if(AVRESAMPLE_INCLUDE_DIR) - include_directories("${AVRESAMPLE_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${AVRESAMPLE_INCLUDE_DIR}") - endif(AVRESAMPLE_INCLUDE_DIR) - mark_as_advanced(FORCE AVRESAMPLE_LIBRARIES AVRESAMPLE_INCLUDE_DIR) - check_include_file("libavresample/avresample.h" HAVE_LIBAVRESAMPLE_AVRESAMPLE_H) - set(optlibsfound "${optlibsfound} AVResample") - else(AVRESAMPLE_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} AVResample") - endif(AVRESAMPLE_LIBRARIES) + # SWresample (using find_library and find_path) + find_library(SWRESAMPLE_LIBRARIES swresample) + if(SWRESAMPLE_LIBRARIES) + set(HAVE_LIBSWRESAMPLE 1) + list(APPEND ZM_BIN_LIBS "${SWRESAMPLE_LIBRARIES}") + find_path(SWRESAMPLE_INCLUDE_DIR "libswresample/swresample.h" /usr/include/ffmpeg) + if(SWRESAMPLE_INCLUDE_DIR) + include_directories("${SWRESAMPLE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${SWRESAMPLE_INCLUDE_DIR}") + endif(SWRESAMPLE_INCLUDE_DIR) + mark_as_advanced(FORCE SWRESAMPLE_LIBRARIES SWRESAMPLE_INCLUDE_DIR) + check_include_file("libswresample/swresample.h" HAVE_LIBSWRESAMPLE_SWRESAMPLE_H) + set(optlibsfound "${optlibsfound} SWResample") + else(SWRESAMPLE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} SWResample") + + # AVresample (using find_library and find_path) + find_library(AVRESAMPLE_LIBRARIES avresample) + if(AVRESAMPLE_LIBRARIES) + set(HAVE_LIBAVRESAMPLE 1) + list(APPEND ZM_BIN_LIBS "${AVRESAMPLE_LIBRARIES}") + find_path(AVRESAMPLE_INCLUDE_DIR "libavresample/avresample.h" /usr/include/ffmpeg) + if(AVRESAMPLE_INCLUDE_DIR) + include_directories("${AVRESAMPLE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${AVRESAMPLE_INCLUDE_DIR}") + endif(AVRESAMPLE_INCLUDE_DIR) + mark_as_advanced(FORCE AVRESAMPLE_LIBRARIES AVRESAMPLE_INCLUDE_DIR) + check_include_file("libavresample/avresample.h" HAVE_LIBAVRESAMPLE_AVRESAMPLE_H) + set(optlibsfound "${optlibsfound} AVResample") + else(AVRESAMPLE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} AVResample") + endif(AVRESAMPLE_LIBRARIES) + + endif(SWRESAMPLE_LIBRARIES) # Find the path to the ffmpeg executable find_program(FFMPEG_EXECUTABLE diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index 991ed9e54..d91fd4f53 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 9), dh-systemd, python-sphinx | python3-sphinx, apa ,libavcodec-dev (>= 6:10~) ,libavformat-dev (>= 6:10~) ,libavutil-dev (>= 6:10~) + ,libswresample-dev ,libswscale-dev (>= 6:10~) ,ffmpeg | libav-tools ,net-tools @@ -41,7 +42,9 @@ Package: zoneminder Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,javascript-common - ,libmp4v2-2, libx264-142|libx264-148|libx264-152, libswscale-ffmpeg3|libswscale4|libswscale3|libswscale5 + ,libmp4v2-2, libx264-142|libx264-148|libx264-152 + ,libswscale-ffmpeg3|libswscale4|libswscale3|libswscale5 + ,libswresample2|libswresample3|libswresample24 ,ffmpeg | libav-tools ,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl ,libdbd-mysql-perl diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 746036efe..31916bdab 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -205,7 +205,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, audio_out_stream = NULL; in_frame = NULL; out_frame = NULL; -#ifdef HAVE_LIBAVRESAMPLE +#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE) resample_ctx = NULL; #endif @@ -220,7 +220,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, audio_in_ctx = audio_in_stream->codec; #endif - if (audio_in_ctx->codec_id != AV_CODEC_ID_AAC) { + if ( audio_in_ctx->codec_id != AV_CODEC_ID_AAC ) { static char error_buffer[256]; avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0); Debug(2, "Got something other than AAC (%s)", error_buffer); @@ -241,8 +241,6 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in, Error("Unable to create audio out stream"); audio_out_stream = NULL; } else { - Debug(2, "setting parameters"); - #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) audio_out_ctx = avcodec_alloc_context3(audio_out_codec); // Copy params from instream to ctx @@ -466,10 +464,16 @@ VideoStore::~VideoStore() { avcodec_free_context(&audio_out_ctx); #endif audio_out_ctx = NULL; -#ifdef HAVE_LIBAVRESAMPLE +#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE) if ( resample_ctx ) { +#if defined(HAVE_LIBSWRESAMPLE) + swr_free(&resample_ctx); +#else +#if defined(HAVE_LIBAVRESAMPLE) avresample_close(resample_ctx); avresample_free(&resample_ctx); +#endif +#endif } if ( in_frame ) { av_frame_free(&in_frame); @@ -491,7 +495,12 @@ VideoStore::~VideoStore() { } // VideoStore::~VideoStore() bool VideoStore::setup_resampler() { -#ifdef HAVE_LIBAVRESAMPLE +#if !defined(HAVE_LIBSWRESAMPLE) && !defined(HAVE_LIBAVRESAMPLE) + Error( + "Not built with resample library. " + "Cannot do audio conversion to AAC"); + return false; +#else #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) // Newer ffmpeg wants to keep everything separate... so have to lookup our own @@ -499,8 +508,7 @@ bool VideoStore::setup_resampler() { audio_in_codec = avcodec_find_decoder(audio_in_stream->codecpar->codec_id); #else - audio_in_codec = - avcodec_find_decoder(audio_in_ctx->codec_id); + audio_in_codec = avcodec_find_decoder(audio_in_ctx->codec_id); #endif ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL); if ( ret < 0 ) { @@ -531,6 +539,9 @@ bool VideoStore::setup_resampler() { audio_out_stream = avformat_new_stream(oc, NULL); audio_out_ctx = audio_out_stream->codec; #endif + // Some formats (i.e. WAV) do not produce the proper channel layout + if ( audio_in_ctx->channel_layout == 0 ) + audio_in_ctx->channel_layout = av_get_channel_layout("mono"); /* put sample parameters */ audio_out_ctx->bit_rate = audio_in_ctx->bit_rate; @@ -622,40 +633,55 @@ bool VideoStore::setup_resampler() { return false; } +#if defined(HAVE_LIBSWRESAMPLE) + resample_ctx = swr_alloc_set_opts(NULL, + av_get_default_channel_layout(audio_out_ctx->channels), + audio_out_ctx->sample_fmt, + audio_out_ctx->sample_rate, + av_get_default_channel_layout(audio_in_ctx->channels), + audio_in_ctx->sample_fmt, + audio_in_ctx->sample_rate, + 0, NULL); + if ( !resample_ctx ) { + Error("Could not allocate resample context"); + av_frame_free(&in_frame); + av_frame_free(&out_frame); + return false; + } + if ( (ret = swr_init(resample_ctx)) < 0 ) { + Error("Could not open resampler"); + av_frame_free(&in_frame); + av_frame_free(&out_frame); + swr_free(&resample_ctx); + return false; + } +#else +#if defined(HAVE_LIBAVRESAMPLE) // Setup the audio resampler resample_ctx = avresample_alloc_context(); if ( !resample_ctx ) { Error("Could not allocate resample ctx"); + av_frame_free(&in_frame); + av_frame_free(&out_frame); return false; } - // Some formats (i.e. WAV) do not produce the proper channel layout - uint64_t layout = av_get_channel_layout("mono"); - if ( audio_in_ctx->channel_layout == 0 ) { - av_opt_set_int(resample_ctx, "in_channel_layout", layout, 0); - Debug(1, "Bad in channel layout. Need to set it to mono (%d).", layout); - } else { - av_opt_set_int(resample_ctx, "in_channel_layout", - audio_in_ctx->channel_layout, 0); - layout = audio_in_ctx->channel_layout; - } - + av_opt_set_int(resample_ctx, "in_channel_layout", + audio_in_ctx->channel_layout, 0); av_opt_set_int(resample_ctx, "in_sample_fmt", - audio_in_ctx->sample_fmt, 0); + audio_in_ctx->sample_fmt, 0); av_opt_set_int(resample_ctx, "in_sample_rate", - audio_in_ctx->sample_rate, 0); - av_opt_set_int(resample_ctx, "in_channels", audio_in_ctx->channels, - 0); - // av_opt_set_int( resample_ctx, "out_channel_layout", - // audio_out_ctx->channel_layout, 0); + audio_in_ctx->sample_rate, 0); + av_opt_set_int(resample_ctx, "in_channels", + audio_in_ctx->channels, 0); av_opt_set_int(resample_ctx, "out_channel_layout", - layout, 0); + audio_in_ctx->channel_layout, 0); av_opt_set_int(resample_ctx, "out_sample_fmt", - audio_out_ctx->sample_fmt, 0); + audio_out_ctx->sample_fmt, 0); av_opt_set_int(resample_ctx, "out_sample_rate", - audio_out_ctx->sample_rate, 0); + audio_out_ctx->sample_rate, 0); av_opt_set_int(resample_ctx, "out_channels", - audio_out_ctx->channels, 0); + audio_out_ctx->channels, 0); ret = avresample_open(resample_ctx); if ( ret < 0 ) { @@ -664,6 +690,8 @@ bool VideoStore::setup_resampler() { } else { Debug(2, "Success opening resampler"); } +#endif +#endif out_frame->nb_samples = audio_out_ctx->frame_size; out_frame->format = audio_out_ctx->sample_fmt; @@ -694,11 +722,6 @@ bool VideoStore::setup_resampler() { } return true; -#else - Error( - "Not built with libavresample library. Cannot do audio conversion to " - "AAC"); - return false; #endif } // end bool VideoStore::setup_resampler() @@ -858,9 +881,9 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { if ( audio_out_codec ) { Debug(3, "Have audio codec"); -#ifdef HAVE_LIBAVRESAMPLE +#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE) -#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) + #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) ret = avcodec_send_packet(audio_in_ctx, ipkt); if ( ret < 0 ) { Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str()); @@ -877,7 +900,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { "layout(%d)", in_frame->nb_samples, in_frame->format, in_frame->sample_rate, in_frame->channel_layout); -#else + #else /** * Decode the audio frame stored in the packet. * The in audio stream decoder is used to do this. @@ -897,11 +920,24 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { Debug(2, "Not ready to transcode a frame yet."); return 0; } -#endif + #endif int frame_size = out_frame->nb_samples; // Resample the in into the audioSampleBuffer until we proceed the whole // decoded data + #if defined(HAVE_LIBSWRESAMPLE) + Debug(2, "Converting %d to %d samples", in_frame->nb_samples, out_frame->nb_samples); + if ((ret = swr_convert(resample_ctx, + out_frame->data, frame_size, + (const uint8_t**)in_frame->data, + in_frame->nb_samples)) < 0) { + Error("Could not resample frame (error '%s')\n", + av_make_error_string(ret).c_str()); + av_frame_unref(in_frame); + return 0; + } + #else + #if defined(HAVE_LIBAVRESAMPLE) if ((ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data, 0, in_frame->nb_samples)) < 0) { @@ -910,8 +946,11 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { av_frame_unref(in_frame); return 0; } + #endif + #endif av_frame_unref(in_frame); + #if defined(HAVE_LIBAVRESAMPLE) int samples_available = avresample_available(resample_ctx); if (samples_available < frame_size) { @@ -926,6 +965,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { Warning("Error reading resampled audio: "); return 0; } + #endif Debug(2, "Frame: samples(%d), format(%d), sample_rate(%d), channel layout(%d)", out_frame->nb_samples, out_frame->format, @@ -934,7 +974,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { av_init_packet(&opkt); Debug(5, "after init packet"); -#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) + #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) if ((ret = avcodec_send_frame(audio_out_ctx, out_frame)) < 0) { Error("Could not send frame (error '%s')", av_make_error_string(ret).c_str()); @@ -958,7 +998,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { // av_frame_unref( out_frame ); return 0; } -#else + #else if ((ret = avcodec_encode_audio2(audio_out_ctx, &opkt, out_frame, &data_present)) < 0) { Error("Could not encode frame (error '%s')", @@ -971,8 +1011,9 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { zm_av_packet_unref(&opkt); return 0; } -#endif - + #endif +#else + Error("Have audio codec but no resampler?!"); #endif } else { av_init_packet(&opkt); diff --git a/src/zm_videostore.h b/src/zm_videostore.h index 282d96da7..bc7cd8417 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -3,8 +3,12 @@ #include "zm_ffmpeg.h" extern "C" { -#ifdef HAVE_LIBAVRESAMPLE -#include "libavresample/avresample.h" +#ifdef HAVE_LIBSWRESAMPLE + #include "libswresample/swresample.h" +#else + #ifdef HAVE_LIBAVRESAMPLE + #include "libavresample/avresample.h" + #endif #endif } @@ -38,8 +42,12 @@ private: // The following are used when encoding the audio stream to AAC AVCodec *audio_out_codec; AVCodecContext *audio_out_ctx; +#ifdef HAVE_LIBSWRESAMPLE + SwrContext *resample_ctx; +#else #ifdef HAVE_LIBAVRESAMPLE AVAudioResampleContext* resample_ctx; +#endif #endif uint8_t *converted_in_samples; diff --git a/zoneminder-config.cmake b/zoneminder-config.cmake index 8641bb4a8..e088e68dc 100644 --- a/zoneminder-config.cmake +++ b/zoneminder-config.cmake @@ -54,6 +54,8 @@ #cmakedefine HAVE_LIBAVUTIL_HWCONTEXT_H 0 #cmakedefine HAVE_LIBSWSCALE 1 #cmakedefine HAVE_LIBSWSCALE_SWSCALE_H 1 +#cmakedefine HAVE_LIBSWRESAMPLE 1 +#cmakedefine HAVE_LIBSWRESAMPLE_SWRESAMPLE_H 1 #cmakedefine HAVE_LIBAVRESAMPLE 1 #cmakedefine HAVE_LIBAVRESAMPLE_AVRESAMPLE_H 1 #cmakedefine HAVE_LIBVLC 1 From a277f697e9212982a48d3f95dba79a3bb74fcbb8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 14:58:38 -0500 Subject: [PATCH 210/240] whitespace --- web/includes/lang.php | 75 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/web/includes/lang.php b/web/includes/lang.php index 0c40e7f60..38f1179d8 100644 --- a/web/includes/lang.php +++ b/web/includes/lang.php @@ -1,6 +1,6 @@ $value) { - if ( ! array_key_exists( $key, $SLANG ) ) - $SLANG[$key] = $DLANG[$key]; - } + require_once($langFile); + require_once('lang/default.php'); + foreach ($DLANG as $key => $value) { + if ( ! array_key_exists($key, $SLANG) ) + $SLANG[$key] = $DLANG[$key]; + } } - // // Date and time formats fallback, if not set up by the language file already // -defined("DATE_FMT_CONSOLE_LONG") or define("DATE_FMT_CONSOLE_LONG", "D jS M, g:ia"); // This is the main console date/time, date() or strftime() format -defined("DATE_FMT_CONSOLE_SHORT") or define( "DATE_FMT_CONSOLE_SHORT", "%H:%M" ); // This is the xHTML console date/time, date() or strftime() format +defined('DATE_FMT_CONSOLE_LONG') or define('DATE_FMT_CONSOLE_LONG', 'D jS M, g:ia'); // This is the main console date/time, date() or strftime() format +defined('DATE_FMT_CONSOLE_SHORT') or define('DATE_FMT_CONSOLE_SHORT', '%H:%M'); // This is the xHTML console date/time, date() or strftime() format -defined("STRF_FMT_DATETIME") or define( "STRF_FMT_DATETIME", "%c" ); // Strftime locale aware format for dates with times -defined("STRF_FMT_DATE") or define( "STRF_FMT_DATE", "%x" ); // Strftime locale aware format for dates without times -defined("STRF_FMT_TIME") or define( "STRF_FMT_TIME", "%X" ); // Strftime locale aware format for times without dates +defined('STRF_FMT_DATETIME') or define('STRF_FMT_DATETIME', '%c'); // Strftime locale aware format for dates with times +defined('STRF_FMT_DATE') or define('STRF_FMT_DATE', '%x'); // Strftime locale aware format for dates without times +defined('STRF_FMT_TIME') or define('STRF_FMT_TIME', '%X'); // Strftime locale aware format for times without dates -defined("STRF_FMT_DATETIME_SHORT") or define( "STRF_FMT_DATETIME_SHORT", "%y/%m/%d %H:%M:%S" ); // Strftime shorter format for dates with time, not locale aware -defined("STRF_FMT_DATETIME_SHORTER") or define( "STRF_FMT_DATETIME_SHORTER", "%m/%d %H:%M:%S" );// Strftime shorter format for dates with time, not locale aware, used where space is tight +defined('STRF_FMT_DATETIME_SHORT') or define('STRF_FMT_DATETIME_SHORT', '%y/%m/%d %H:%M:%S'); // Strftime shorter format for dates with time, not locale aware +defined('STRF_FMT_DATETIME_SHORTER') or define('STRF_FMT_DATETIME_SHORTER','%m/%d %H:%M:%S');// Strftime shorter format for dates with time, not locale aware, used where space is tight ?> From 48865f124b17b1758ed81e843332a384236ed489 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 20 Dec 2018 15:10:04 -0500 Subject: [PATCH 211/240] cap AAC bitrate at 96000 to prevent the aac encoder from complaining --- src/zm_videostore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 746036efe..ee4ff268b 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -533,7 +533,7 @@ bool VideoStore::setup_resampler() { #endif /* put sample parameters */ - audio_out_ctx->bit_rate = audio_in_ctx->bit_rate; + audio_out_ctx->bit_rate = audio_in_ctx->bit_rate <= 96000 ? audio_in_ctx->bit_rate : 96000; audio_out_ctx->sample_rate = audio_in_ctx->sample_rate; audio_out_ctx->channels = audio_in_ctx->channels; audio_out_ctx->channel_layout = audio_in_ctx->channel_layout; From 47465260d163f19792e34a2a2054057f0cdf19db Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 21 Dec 2018 10:01:48 -0500 Subject: [PATCH 212/240] Update permissions checking for Groups to not use session. Fixes #2353 --- web/api/app/Controller/GroupsController.php | 73 ++++++++++++++------- web/api/app/Model/Group.php | 4 +- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/web/api/app/Controller/GroupsController.php b/web/api/app/Controller/GroupsController.php index 7859f492e..6f0a88300 100644 --- a/web/api/app/Controller/GroupsController.php +++ b/web/api/app/Controller/GroupsController.php @@ -16,8 +16,10 @@ class GroupsController extends AppController { public function beforeFilter() { parent::beforeFilter(); - $canView = $this->Session->Read('groupsPermission'); - if ( $canView == 'None' ) { + global $user; + # We already tested for auth in appController, so we just need to test for specific permission + $canView = (!$user) || ($user['Groups'] != 'None'); + if ( !$canView ) { throw new UnauthorizedException(__('Insufficient Privileges')); return; } @@ -63,16 +65,23 @@ class GroupsController extends AppController { * @return void */ public function add() { - if ($this->request->is('post')) { + if ( $this->request->is('post') ) { - if ($this->Session->Read('groupPermission') != 'Edit') { - throw new UnauthorizedException(__('Insufficient privileges')); + global $user; + # We already tested for auth in appController, + # so we just need to test for specific permission + $canEdit = (!$user) || ($user['Groups'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient Privileges')); return; - } + } $this->Group->create(); - if ($this->Group->save($this->request->data)) { - return $this->flash(__('The group has been saved.'), array('action' => 'index')); + if ( $this->Group->save($this->request->data) ) { + return $this->flash( + __('The group has been saved.'), + array('action' => 'index') + ); } } $monitors = $this->Group->Monitor->find('list'); @@ -86,17 +95,24 @@ class GroupsController extends AppController { * @param string $id * @return void */ - public function edit($id = null) { - if (!$this->Group->exists($id)) { + public function edit( $id = null ) { + if ( !$this->Group->exists($id) ) { throw new NotFoundException(__('Invalid group')); } if ( $this->request->is(array('post', 'put'))) { - if ( $this->Session->Read('groupPermission') != 'Edit' ) { - throw new UnauthorizedException(__('Insufficient privileges')); + global $user; + # We already tested for auth in appController, + # so we just need to test for specific permission + $canEdit = (!$user) || ($user['Groups'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient Privileges')); return; } - if ($this->Group->save($this->request->data)) { - return $this->flash(__('The group has been saved.'), array('action' => 'index')); + if ( $this->Group->save($this->request->data) ) { + return $this->flash( + __('The group has been saved.'), + array('action' => 'index') + ); } else { $message = 'Error'; } @@ -108,7 +124,7 @@ class GroupsController extends AppController { $this->set(array( 'message' => $message, 'monitors'=> $monitors, - '_serialize' => array('message',) + '_serialize' => array('message') )); } @@ -121,19 +137,30 @@ class GroupsController extends AppController { */ public function delete($id = null) { $this->Group->id = $id; - if (!$this->Group->exists()) { + if ( !$this->Group->exists() ) { throw new NotFoundException(__('Invalid group')); } $this->request->allowMethod('post', 'delete'); - if ( $this->Session->Read('groupPermission') != 'Edit' ) { - throw new UnauthorizedException(__('Insufficient privileges')); - return; - } - if ($this->Group->delete()) { - return $this->flash(__('The group has been deleted.'), array('action' => 'index')); + global $user; + # We already tested for auth in appController, + # so we just need to test for specific permission + $canEdit = (!$user) || ($user['Groups'] == 'Edit'); + if ( !$canEdit ) { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } + + if ( $this->Group->delete() ) { + return $this->flash( + __('The group has been deleted.'), + array('action' => 'index') + ); } else { - return $this->flash(__('The group could not be deleted. Please, try again.'), array('action' => 'index')); + return $this->flash( + __('The group could not be deleted. Please, try again.'), + array('action' => 'index') + ); } } // end function delete } // end class GroupController diff --git a/web/api/app/Model/Group.php b/web/api/app/Model/Group.php index e27460424..108f9b9c7 100644 --- a/web/api/app/Model/Group.php +++ b/web/api/app/Model/Group.php @@ -38,8 +38,8 @@ class Group extends AppModel { */ public $validate = array( 'Name' => array( - 'notEmpty' => array( - 'rule' => array('notEmpty'))), + 'notBlank' => array( + 'rule' => array('notBlank'))), 'Id' => array( 'numeric' => array( 'rule' => array('numeric'), From 1130d6650aac96d229410754103227996c5cf173 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 21 Dec 2018 10:50:19 -0500 Subject: [PATCH 213/240] Fix spacing and pass popup to previous/next event so that popups stay as popups --- web/skins/classic/views/event.php | 11 ++++++----- web/skins/classic/views/js/event.js | 8 ++++---- web/skins/classic/views/js/event.js.php | 1 + 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index bc8fa324e..3312a8d07 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -46,18 +46,19 @@ if (isset($_REQUEST['rate'])) { if (isset($_REQUEST['scale'])) { $scale = validInt($_REQUEST['scale']); -} else if ( isset( $_COOKIE['zmEventScaleAuto'] ) ) { //If we're using scale to fit use it on all monitors +} else if ( isset( $_COOKIE['zmEventScaleAuto'] ) ) { + // If we're using scale to fit use it on all monitors $scale = 'auto'; } else if ( isset( $_COOKIE['zmEventScale'.$Event->MonitorId()] ) ) { $scale = $_COOKIE['zmEventScale'.$Event->MonitorId()]; } else { - $scale = reScale( SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE ); + $scale = reScale(SCALE_BASE, $Monitor->DefaultScale(), ZM_WEB_DEFAULT_SCALE); } $replayModes = array( - 'none' => translate('None'), - 'single' => translate('ReplaySingle'), - 'all' => translate('ReplayAll'), + 'none' => translate('None'), + 'single' => translate('ReplaySingle'), + 'all' => translate('ReplayAll'), 'gapless' => translate('ReplayGapless'), ); diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index d438aa5a0..c1f71697e 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -400,14 +400,14 @@ function streamFastRev( action ) { function streamPrev(action) { if ( action ) { $j(".vjsMessage").remove(); - location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery); + location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery + '&popup='+popup); return; if ( vid && PrevEventDefVideoPath.indexOf("view_video") > 0 ) { CurEventDefVideoPath = PrevEventDefVideoPath; eventQuery(prevEventId); } else if (zmsBroke || (vid && PrevEventDefVideoPath.indexOf("view_video") < 0) || $j("#vjsMessage").length || PrevEventDefVideoPath.indexOf("view_video") > 0) {//zms broke, leaving videojs, last event, moving to videojs - location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery); + location.replace(thisUrl + '?view=event&eid=' + prevEventId + filterQuery + sortQuery + '&popup='+popup); } else { streamReq.send(streamParms+"&command="+CMD_PREV); streamPlay(); @@ -429,13 +429,13 @@ function streamNext(action) { // We used to try to dynamically update all the bits in the page, which is really complex // How about we just reload the page? // - location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery); + location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery + '&popup='+popup); return; if ( vid && ( NextEventDefVideoPath.indexOf("view_video") > 0 ) ) { //on and staying with videojs CurEventDefVideoPath = NextEventDefVideoPath; eventQuery(nextEventId); } else if ( zmsBroke || (vid && NextEventDefVideoPath.indexOf("view_video") < 0) || NextEventDefVideoPath.indexOf("view_video") > 0) {//reload zms, leaving vjs, moving to vjs - location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery); + location.replace(thisUrl + '?view=event&eid=' + nextEventId + filterQuery + sortQuery + '&popup='+popup); } else { streamReq.send(streamParms+"&command="+CMD_NEXT); streamPlay(); diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php index 8783bbe06..5df0be70d 100644 --- a/web/skins/classic/views/js/event.js.php +++ b/web/skins/classic/views/js/event.js.php @@ -58,3 +58,4 @@ var deleteString = ""; var causeString = ""; var WEB_LIST_THUMB_WIDTH = ''; var WEB_LIST_THUMB_HEIGHT = ''; +var popup = ''; From 0cce0a642b710b41fe70d189a92cdff10737779c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 24 Dec 2018 09:37:49 -0500 Subject: [PATCH 214/240] Update chosen library to 1.8.7 --- web/skins/classic/js/chosen/chosen.css | 10 +++++-- web/skins/classic/js/chosen/chosen.jquery.js | 30 ++++++++++++------- .../classic/js/chosen/chosen.jquery.min.js | 4 +-- web/skins/classic/js/chosen/chosen.min.css | 6 ++-- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/web/skins/classic/js/chosen/chosen.css b/web/skins/classic/js/chosen/chosen.css index d4219b491..5ae6fc94c 100644 --- a/web/skins/classic/js/chosen/chosen.css +++ b/web/skins/classic/js/chosen/chosen.css @@ -2,9 +2,9 @@ Chosen, a Select Box Enhancer for jQuery and Prototype by Patrick Filler for Harvest, http://getharvest.com -Version 1.8.2 +Version 1.8.7 Full source at https://github.com/harvesthq/chosen -Copyright (c) 2011-2017 Harvest http://getharvest.com +Copyright (c) 2011-2018 Harvest http://getharvest.com MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md This file is generated by `grunt build`, do not edit it by hand. @@ -38,10 +38,14 @@ This file is generated by `grunt build`, do not edit it by hand. -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); clip: rect(0, 0, 0, 0); + -webkit-clip-path: inset(100% 100%); + clip-path: inset(100% 100%); } .chosen-container.chosen-with-drop .chosen-drop { clip: auto; + -webkit-clip-path: none; + clip-path: none; } .chosen-container a { @@ -167,6 +171,8 @@ This file is generated by `grunt build`, do not edit it by hand. .chosen-container-single.chosen-container-single-nosearch .chosen-search { position: absolute; clip: rect(0, 0, 0, 0); + -webkit-clip-path: inset(100% 100%); + clip-path: inset(100% 100%); } /* @end */ diff --git a/web/skins/classic/js/chosen/chosen.jquery.js b/web/skins/classic/js/chosen/chosen.jquery.js index b8e20eb73..af0985d8c 100644 --- a/web/skins/classic/js/chosen/chosen.jquery.js +++ b/web/skins/classic/js/chosen/chosen.jquery.js @@ -2,9 +2,9 @@ Chosen, a Select Box Enhancer for jQuery and Prototype by Patrick Filler for Harvest, http://getharvest.com -Version 1.8.2 +Version 1.8.7 Full source at https://github.com/harvesthq/chosen -Copyright (c) 2011-2017 Harvest http://getharvest.com +Copyright (c) 2011-2018 Harvest http://getharvest.com MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md This file is generated by `grunt build`, do not edit it by hand. @@ -161,7 +161,7 @@ This file is generated by `grunt build`, do not edit it by hand. AbstractChosen.prototype.choice_label = function(item) { if (this.include_group_label_in_selected && (item.group_label != null)) { - return "" + item.group_label + "" + item.html; + return "" + (this.escape_html(item.group_label)) + "" + item.html; } else { return item.html; } @@ -267,7 +267,9 @@ This file is generated by `grunt build`, do not edit it by hand. } option_el = document.createElement("li"); option_el.className = classes.join(" "); - option_el.style.cssText = option.style; + if (option.style) { + option_el.style.cssText = option.style; + } option_el.setAttribute("data-option-array-index", option.array_index); option_el.innerHTML = option.highlighted_html || option.html; if (option.title) { @@ -341,7 +343,7 @@ This file is generated by `grunt build`, do not edit it by hand. } }; - AbstractChosen.prototype.winnow_results = function() { + AbstractChosen.prototype.winnow_results = function(options) { var escapedQuery, fix, i, len, option, prefix, query, ref, regex, results, results_group, search_match, startpos, suffix, text; this.no_results_clear(); results = 0; @@ -397,7 +399,9 @@ This file is generated by `grunt build`, do not edit it by hand. return this.no_results(query); } else { this.update_results_content(this.results_option_build()); - return this.winnow_results_set_highlight(); + if (!(options != null ? options.skip_highlight : void 0)) { + return this.winnow_results_set_highlight(); + } } }; @@ -540,7 +544,7 @@ This file is generated by `grunt build`, do not edit it by hand. if (this.options.width != null) { return this.options.width; } else { - return this.form_field.offsetWidth + "px"; + return this.form_field.offsetWidth+15 + "px"; } }; @@ -941,7 +945,7 @@ This file is generated by `grunt build`, do not edit it by hand. this.results_data = SelectParser.select_to_array(this.form_field); if (this.is_multiple) { this.search_choices.find("li.search-choice").remove(); - } else if (!this.is_multiple) { + } else { this.single_set_selected_text(); if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) { this.search_field[0].readOnly = true; @@ -1154,14 +1158,20 @@ This file is generated by `grunt build`, do not edit it by hand. item.selected = true; this.form_field.options[item.options_index].selected = true; this.selected_option_count = null; - this.search_field.val(""); if (this.is_multiple) { this.choice_build(item); } else { this.single_set_selected_text(this.choice_label(item)); } if (this.is_multiple && (!this.hide_results_on_select || (evt.metaKey || evt.ctrlKey))) { - this.winnow_results(); + if (evt.metaKey || evt.ctrlKey) { + this.winnow_results({ + skip_highlight: true + }); + } else { + this.search_field.val(""); + this.winnow_results(); + } } else { this.results_hide(); this.show_search_field_default(); diff --git a/web/skins/classic/js/chosen/chosen.jquery.min.js b/web/skins/classic/js/chosen/chosen.jquery.min.js index d67677fbd..4ad164751 100644 --- a/web/skins/classic/js/chosen/chosen.jquery.min.js +++ b/web/skins/classic/js/chosen/chosen.jquery.min.js @@ -1,3 +1,3 @@ -/* Chosen v1.8.2 | (c) 2011-2017 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ +/* Chosen v1.8.7 | (c) 2011-2018 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ -(function(){var t,e,s,i,n=function(t,e){return function(){return t.apply(e,arguments)}},r=function(t,e){function s(){this.constructor=t}for(var i in e)o.call(e,i)&&(t[i]=e[i]);return s.prototype=e.prototype,t.prototype=new s,t.__super__=e.prototype,t},o={}.hasOwnProperty;(i=function(){function t(){this.options_index=0,this.parsed=[]}return t.prototype.add_node=function(t){return"OPTGROUP"===t.nodeName.toUpperCase()?this.add_group(t):this.add_option(t)},t.prototype.add_group=function(t){var e,s,i,n,r,o;for(e=this.parsed.length,this.parsed.push({array_index:e,group:!0,label:t.label,title:t.title?t.title:void 0,children:0,disabled:t.disabled,classes:t.className}),o=[],s=0,i=(r=t.childNodes).length;s"+t.group_label+""+t.html:t.html},t.prototype.mouse_enter=function(){return this.mouse_on_container=!0},t.prototype.mouse_leave=function(){return this.mouse_on_container=!1},t.prototype.input_focus=function(t){if(this.is_multiple){if(!this.active_field)return setTimeout(function(t){return function(){return t.container_mousedown()}}(this),50)}else if(!this.active_field)return this.activate_field()},t.prototype.input_blur=function(t){if(!this.mouse_on_container)return this.active_field=!1,setTimeout(function(t){return function(){return t.blur_test()}}(this),100)},t.prototype.label_click_handler=function(t){return this.is_multiple?this.container_mousedown(t):this.activate_field()},t.prototype.results_option_build=function(t){var e,s,i,n,r,o,h;for(e="",h=0,n=0,r=(o=this.results_data).length;n=this.max_shown_results));n++);return e},t.prototype.result_add_option=function(t){var e,s;return t.search_match&&this.include_option_in_results(t)?(e=[],t.disabled||t.selected&&this.is_multiple||e.push("active-result"),!t.disabled||t.selected&&this.is_multiple||e.push("disabled-result"),t.selected&&e.push("result-selected"),null!=t.group_array_index&&e.push("group-option"),""!==t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.style.cssText=t.style,s.setAttribute("data-option-array-index",t.array_index),s.innerHTML=t.highlighted_html||t.html,t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.result_add_group=function(t){var e,s;return(t.search_match||t.group_match)&&t.active_options>0?((e=[]).push("group-result"),t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.innerHTML=t.highlighted_html||this.escape_html(t.label),t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.results_update_field=function(){if(this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing)return this.winnow_results()},t.prototype.reset_single_select_options=function(){var t,e,s,i,n;for(n=[],t=0,e=(s=this.results_data).length;t"+this.escape_html(e)+""+this.escape_html(d)),null!=_&&(_.group_match=!0)):null!=n.group_array_index&&this.results_data[n.group_array_index].search_match&&(n.search_match=!0)));return this.result_clear_highlight(),c<1&&o.length?(this.update_results_content(""),this.no_results(o)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},t.prototype.get_search_regex=function(t){var e,s;return s=this.search_contains?t:"(^|\\s|\\b)"+t+"[^\\s]*",this.enable_split_word_search||this.search_contains||(s="^"+s),e=this.case_sensitive_search?"":"i",new RegExp(s,e)},t.prototype.search_string_match=function(t,e){var s;return s=e.exec(t),!this.search_contains&&(null!=s?s[1]:void 0)&&(s.index+=1),s},t.prototype.choices_count=function(){var t,e,s;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,t=0,e=(s=this.form_field.options).length;t0?this.keydown_backstroke():this.pending_backstroke||(this.result_clear_highlight(),this.results_search());break;case 13:t.preventDefault(),this.results_showing&&this.result_select(t);break;case 27:this.results_showing&&this.results_hide();break;case 9:case 16:case 17:case 18:case 38:case 40:case 91:break;default:this.results_search()}},t.prototype.clipboard_event_checker=function(t){if(!this.is_disabled)return setTimeout(function(t){return function(){return t.results_search()}}(this),50)},t.prototype.container_width=function(){return null!=this.options.width?this.options.width:this.form_field.offsetWidth+"px"},t.prototype.include_option_in_results=function(t){return!(this.is_multiple&&!this.display_selected_options&&t.selected)&&(!(!this.display_disabled_options&&t.disabled)&&!t.empty)},t.prototype.search_results_touchstart=function(t){return this.touch_started=!0,this.search_results_mouseover(t)},t.prototype.search_results_touchmove=function(t){return this.touch_started=!1,this.search_results_mouseout(t)},t.prototype.search_results_touchend=function(t){if(this.touch_started)return this.search_results_mouseup(t)},t.prototype.outerHTML=function(t){var e;return t.outerHTML?t.outerHTML:((e=document.createElement("div")).appendChild(t),e.innerHTML)},t.prototype.get_single_html=function(){return'\n '+this.default_text+'\n
\n
\n
\n \n
    \n
    '},t.prototype.get_multi_html=function(){return'
      \n
    • \n \n
    • \n
    \n
    \n
      \n
      '},t.prototype.get_no_results_html=function(t){return'
    • \n '+this.results_none_found+" "+this.escape_html(t)+"\n
    • "},t.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!(/iP(od|hone)/i.test(window.navigator.userAgent)||/IEMobile/i.test(window.navigator.userAgent)||/Windows Phone/i.test(window.navigator.userAgent)||/BlackBerry/i.test(window.navigator.userAgent)||/BB10/i.test(window.navigator.userAgent)||/Android.*Mobile/i.test(window.navigator.userAgent))},t.default_multiple_text="Select Some Options",t.default_single_text="Select an Option",t.default_no_result_text="No results match",t}(),(t=jQuery).fn.extend({chosen:function(i){return e.browser_is_supported()?this.each(function(e){var n,r;r=(n=t(this)).data("chosen"),"destroy"!==i?r instanceof s||n.data("chosen",new s(this,i)):r instanceof s&&r.destroy()}):this}}),s=function(s){function n(){return n.__super__.constructor.apply(this,arguments)}return r(n,e),n.prototype.setup=function(){return this.form_field_jq=t(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex},n.prototype.set_up_html=function(){var e,s;return(e=["chosen-container"]).push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&e.push(this.form_field.className),this.is_rtl&&e.push("chosen-rtl"),s={"class":e.join(" "),title:this.form_field.title},this.form_field.id.length&&(s.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=t("
      ",s),this.container.width(this.container_width()),this.is_multiple?this.container.html(this.get_multi_html()):this.container.html(this.get_single_html()),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior()},n.prototype.on_ready=function(){return this.form_field_jq.trigger("chosen:ready",{chosen:this})},n.prototype.register_observers=function(){return this.container.on("touchstart.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("touchend.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mousedown.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("mouseup.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mouseenter.chosen",function(t){return function(e){t.mouse_enter(e)}}(this)),this.container.on("mouseleave.chosen",function(t){return function(e){t.mouse_leave(e)}}(this)),this.search_results.on("mouseup.chosen",function(t){return function(e){t.search_results_mouseup(e)}}(this)),this.search_results.on("mouseover.chosen",function(t){return function(e){t.search_results_mouseover(e)}}(this)),this.search_results.on("mouseout.chosen",function(t){return function(e){t.search_results_mouseout(e)}}(this)),this.search_results.on("mousewheel.chosen DOMMouseScroll.chosen",function(t){return function(e){t.search_results_mousewheel(e)}}(this)),this.search_results.on("touchstart.chosen",function(t){return function(e){t.search_results_touchstart(e)}}(this)),this.search_results.on("touchmove.chosen",function(t){return function(e){t.search_results_touchmove(e)}}(this)),this.search_results.on("touchend.chosen",function(t){return function(e){t.search_results_touchend(e)}}(this)),this.form_field_jq.on("chosen:updated.chosen",function(t){return function(e){t.results_update_field(e)}}(this)),this.form_field_jq.on("chosen:activate.chosen",function(t){return function(e){t.activate_field(e)}}(this)),this.form_field_jq.on("chosen:open.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.form_field_jq.on("chosen:close.chosen",function(t){return function(e){t.close_field(e)}}(this)),this.search_field.on("blur.chosen",function(t){return function(e){t.input_blur(e)}}(this)),this.search_field.on("keyup.chosen",function(t){return function(e){t.keyup_checker(e)}}(this)),this.search_field.on("keydown.chosen",function(t){return function(e){t.keydown_checker(e)}}(this)),this.search_field.on("focus.chosen",function(t){return function(e){t.input_focus(e)}}(this)),this.search_field.on("cut.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.search_field.on("paste.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.is_multiple?this.search_choices.on("click.chosen",function(t){return function(e){t.choices_click(e)}}(this)):this.container.on("click.chosen",function(t){t.preventDefault()})},n.prototype.destroy=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.form_field_label.length>0&&this.form_field_label.off("click.chosen"),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},n.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field.disabled||this.form_field_jq.parents("fieldset").is(":disabled"),this.container.toggleClass("chosen-disabled",this.is_disabled),this.search_field[0].disabled=this.is_disabled,this.is_multiple||this.selected_item.off("focus.chosen",this.activate_field),this.is_disabled?this.close_field():this.is_multiple?void 0:this.selected_item.on("focus.chosen",this.activate_field)},n.prototype.container_mousedown=function(e){var s;if(!this.is_disabled)return!e||"mousedown"!==(s=e.type)&&"touchstart"!==s||this.results_showing||e.preventDefault(),null!=e&&t(e.target).hasClass("search-choice-close")?void 0:(this.active_field?this.is_multiple||!e||t(e.target)[0]!==this.selected_item[0]&&!t(e.target).parents("a.chosen-single").length||(e.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),t(this.container[0].ownerDocument).on("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},n.prototype.container_mouseup=function(t){if("ABBR"===t.target.nodeName&&!this.is_disabled)return this.results_reset(t)},n.prototype.search_results_mousewheel=function(t){var e;if(t.originalEvent&&(e=t.originalEvent.deltaY||-t.originalEvent.wheelDelta||t.originalEvent.detail),null!=e)return t.preventDefault(),"DOMMouseScroll"===t.type&&(e*=40),this.search_results.scrollTop(e+this.search_results.scrollTop())},n.prototype.blur_test=function(t){if(!this.active_field&&this.container.hasClass("chosen-container-active"))return this.close_field()},n.prototype.close_field=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale(),this.search_field.blur()},n.prototype.activate_field=function(){if(!this.is_disabled)return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},n.prototype.test_active_click=function(e){var s;return(s=t(e.target).closest(".chosen-container")).length&&this.container[0]===s[0]?this.active_field=!0:this.close_field()},n.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=i.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},n.prototype.result_do_highlight=function(t){var e,s,i,n,r;if(t.length){if(this.result_clear_highlight(),this.result_highlight=t,this.result_highlight.addClass("highlighted"),i=parseInt(this.search_results.css("maxHeight"),10),r=this.search_results.scrollTop(),n=i+r,s=this.result_highlight.position().top+this.search_results.scrollTop(),(e=s+this.result_highlight.outerHeight())>=n)return this.search_results.scrollTop(e-i>0?e-i:0);if(s0)return this.form_field_label.on("click.chosen",this.label_click_handler)},n.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},n.prototype.search_results_mouseup=function(e){var s;if((s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first()).length)return this.result_highlight=s,this.result_select(e),this.search_field.focus()},n.prototype.search_results_mouseover=function(e){var s;if(s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first())return this.result_do_highlight(s)},n.prototype.search_results_mouseout=function(e){if(t(e.target).hasClass("active-result")||t(e.target).parents(".active-result").first())return this.result_clear_highlight()},n.prototype.choice_build=function(e){var s,i;return s=t("
    • ",{"class":"search-choice"}).html(""+this.choice_label(e)+""),e.disabled?s.addClass("search-choice-disabled"):((i=t("",{"class":"search-choice-close","data-option-array-index":e.array_index})).on("click.chosen",function(t){return function(e){return t.choice_destroy_link_click(e)}}(this)),s.append(i)),this.search_container.before(s)},n.prototype.choice_destroy_link_click=function(e){if(e.preventDefault(),e.stopPropagation(),!this.is_disabled)return this.choice_destroy(t(e.target))},n.prototype.choice_destroy=function(t){if(this.result_deselect(t[0].getAttribute("data-option-array-index")))return this.active_field?this.search_field.focus():this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.get_search_field_value().length<1&&this.results_hide(),t.parents("li").first().remove(),this.search_field_scale()},n.prototype.results_reset=function(){if(this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.trigger_form_field_change(),this.active_field)return this.results_hide()},n.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},n.prototype.result_select=function(t){var e,s;if(this.result_highlight)return e=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?e.removeClass("active-result"):this.reset_single_select_options(),e.addClass("result-selected"),s=this.results_data[e[0].getAttribute("data-option-array-index")],s.selected=!0,this.form_field.options[s.options_index].selected=!0,this.selected_option_count=null,this.search_field.val(""),this.is_multiple?this.choice_build(s):this.single_set_selected_text(this.choice_label(s)),this.is_multiple&&(!this.hide_results_on_select||t.metaKey||t.ctrlKey)?this.winnow_results():(this.results_hide(),this.show_search_field_default()),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.trigger_form_field_change({selected:this.form_field.options[s.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,t.preventDefault(),this.search_field_scale())},n.prototype.single_set_selected_text=function(t){return null==t&&(t=this.default_text),t===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").html(t)},n.prototype.result_deselect=function(t){var e;return e=this.results_data[t],!this.form_field.options[e.options_index].disabled&&(e.selected=!1,this.form_field.options[e.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.trigger_form_field_change({deselected:this.form_field.options[e.options_index].value}),this.search_field_scale(),!0)},n.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect)return this.selected_item.find("abbr").length||this.selected_item.find("span").first().after(''),this.selected_item.addClass("chosen-single-with-deselect")},n.prototype.get_search_field_value=function(){return this.search_field.val()},n.prototype.get_search_text=function(){return t.trim(this.get_search_field_value())},n.prototype.escape_html=function(e){return t("
      ").text(e).html()},n.prototype.winnow_results_set_highlight=function(){var t,e;if(e=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),null!=(t=e.length?e.first():this.search_results.find(".active-result").first()))return this.result_do_highlight(t)},n.prototype.no_results=function(t){var e;return e=this.get_no_results_html(t),this.search_results.append(e),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},n.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},n.prototype.keydown_arrow=function(){var t;return this.results_showing&&this.result_highlight?(t=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(t):void 0:this.results_show()},n.prototype.keyup_arrow=function(){var t;return this.results_showing||this.is_multiple?this.result_highlight?(t=this.result_highlight.prevAll("li.active-result")).length?this.result_do_highlight(t.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight()):void 0:this.results_show()},n.prototype.keydown_backstroke=function(){var t;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(t=this.search_container.siblings("li.search-choice").last()).length&&!t.hasClass("search-choice-disabled")?(this.pending_backstroke=t,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0},n.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},n.prototype.search_field_scale=function(){var e,s,i,n,r,o,h;if(this.is_multiple){for(r={position:"absolute",left:"-1000px",top:"-1000px",display:"none",whiteSpace:"pre"},s=0,i=(o=["fontSize","fontStyle","fontWeight","fontFamily","lineHeight","textTransform","letterSpacing"]).length;s").css(r)).text(this.get_search_field_value()),t("body").append(e),h=e.width()+25,e.remove(),this.container.is(":visible")&&(h=Math.min(this.container.outerWidth()-10,h)),this.search_field.width(h)}},n.prototype.trigger_form_field_change=function(t){return this.form_field_jq.trigger("input",t),this.form_field_jq.trigger("change",t)},n}()}).call(this); \ No newline at end of file +(function(){var t,e,s,i,n=function(t,e){return function(){return t.apply(e,arguments)}},r=function(t,e){function s(){this.constructor=t}for(var i in e)o.call(e,i)&&(t[i]=e[i]);return s.prototype=e.prototype,t.prototype=new s,t.__super__=e.prototype,t},o={}.hasOwnProperty;(i=function(){function t(){this.options_index=0,this.parsed=[]}return t.prototype.add_node=function(t){return"OPTGROUP"===t.nodeName.toUpperCase()?this.add_group(t):this.add_option(t)},t.prototype.add_group=function(t){var e,s,i,n,r,o;for(e=this.parsed.length,this.parsed.push({array_index:e,group:!0,label:t.label,title:t.title?t.title:void 0,children:0,disabled:t.disabled,classes:t.className}),o=[],s=0,i=(r=t.childNodes).length;s"+this.escape_html(t.group_label)+""+t.html:t.html},t.prototype.mouse_enter=function(){return this.mouse_on_container=!0},t.prototype.mouse_leave=function(){return this.mouse_on_container=!1},t.prototype.input_focus=function(t){if(this.is_multiple){if(!this.active_field)return setTimeout(function(t){return function(){return t.container_mousedown()}}(this),50)}else if(!this.active_field)return this.activate_field()},t.prototype.input_blur=function(t){if(!this.mouse_on_container)return this.active_field=!1,setTimeout(function(t){return function(){return t.blur_test()}}(this),100)},t.prototype.label_click_handler=function(t){return this.is_multiple?this.container_mousedown(t):this.activate_field()},t.prototype.results_option_build=function(t){var e,s,i,n,r,o,h;for(e="",h=0,n=0,r=(o=this.results_data).length;n=this.max_shown_results));n++);return e},t.prototype.result_add_option=function(t){var e,s;return t.search_match&&this.include_option_in_results(t)?(e=[],t.disabled||t.selected&&this.is_multiple||e.push("active-result"),!t.disabled||t.selected&&this.is_multiple||e.push("disabled-result"),t.selected&&e.push("result-selected"),null!=t.group_array_index&&e.push("group-option"),""!==t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),t.style&&(s.style.cssText=t.style),s.setAttribute("data-option-array-index",t.array_index),s.innerHTML=t.highlighted_html||t.html,t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.result_add_group=function(t){var e,s;return(t.search_match||t.group_match)&&t.active_options>0?((e=[]).push("group-result"),t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.innerHTML=t.highlighted_html||this.escape_html(t.label),t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.results_update_field=function(){if(this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing)return this.winnow_results()},t.prototype.reset_single_select_options=function(){var t,e,s,i,n;for(n=[],t=0,e=(s=this.results_data).length;t"+this.escape_html(s)+""+this.escape_html(p)),null!=a&&(a.group_match=!0)):null!=r.group_array_index&&this.results_data[r.group_array_index].search_match&&(r.search_match=!0)));return this.result_clear_highlight(),_<1&&h.length?(this.update_results_content(""),this.no_results(h)):(this.update_results_content(this.results_option_build()),(null!=t?t.skip_highlight:void 0)?void 0:this.winnow_results_set_highlight())},t.prototype.get_search_regex=function(t){var e,s;return s=this.search_contains?t:"(^|\\s|\\b)"+t+"[^\\s]*",this.enable_split_word_search||this.search_contains||(s="^"+s),e=this.case_sensitive_search?"":"i",new RegExp(s,e)},t.prototype.search_string_match=function(t,e){var s;return s=e.exec(t),!this.search_contains&&(null!=s?s[1]:void 0)&&(s.index+=1),s},t.prototype.choices_count=function(){var t,e,s;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,t=0,e=(s=this.form_field.options).length;t0?this.keydown_backstroke():this.pending_backstroke||(this.result_clear_highlight(),this.results_search());break;case 13:t.preventDefault(),this.results_showing&&this.result_select(t);break;case 27:this.results_showing&&this.results_hide();break;case 9:case 16:case 17:case 18:case 38:case 40:case 91:break;default:this.results_search()}},t.prototype.clipboard_event_checker=function(t){if(!this.is_disabled)return setTimeout(function(t){return function(){return t.results_search()}}(this),50)},t.prototype.container_width=function(){return null!=this.options.width?this.options.width:this.form_field.offsetWidth+"px"},t.prototype.include_option_in_results=function(t){return!(this.is_multiple&&!this.display_selected_options&&t.selected)&&(!(!this.display_disabled_options&&t.disabled)&&!t.empty)},t.prototype.search_results_touchstart=function(t){return this.touch_started=!0,this.search_results_mouseover(t)},t.prototype.search_results_touchmove=function(t){return this.touch_started=!1,this.search_results_mouseout(t)},t.prototype.search_results_touchend=function(t){if(this.touch_started)return this.search_results_mouseup(t)},t.prototype.outerHTML=function(t){var e;return t.outerHTML?t.outerHTML:((e=document.createElement("div")).appendChild(t),e.innerHTML)},t.prototype.get_single_html=function(){return'\n '+this.default_text+'\n
      \n
      \n
      \n \n
        \n
        '},t.prototype.get_multi_html=function(){return'
          \n
        • \n \n
        • \n
        \n
        \n
          \n
          '},t.prototype.get_no_results_html=function(t){return'
        • \n '+this.results_none_found+" "+this.escape_html(t)+"\n
        • "},t.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!(/iP(od|hone)/i.test(window.navigator.userAgent)||/IEMobile/i.test(window.navigator.userAgent)||/Windows Phone/i.test(window.navigator.userAgent)||/BlackBerry/i.test(window.navigator.userAgent)||/BB10/i.test(window.navigator.userAgent)||/Android.*Mobile/i.test(window.navigator.userAgent))},t.default_multiple_text="Select Some Options",t.default_single_text="Select an Option",t.default_no_result_text="No results match",t}(),(t=jQuery).fn.extend({chosen:function(i){return e.browser_is_supported()?this.each(function(e){var n,r;r=(n=t(this)).data("chosen"),"destroy"!==i?r instanceof s||n.data("chosen",new s(this,i)):r instanceof s&&r.destroy()}):this}}),s=function(s){function n(){return n.__super__.constructor.apply(this,arguments)}return r(n,e),n.prototype.setup=function(){return this.form_field_jq=t(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex},n.prototype.set_up_html=function(){var e,s;return(e=["chosen-container"]).push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&e.push(this.form_field.className),this.is_rtl&&e.push("chosen-rtl"),s={"class":e.join(" "),title:this.form_field.title},this.form_field.id.length&&(s.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=t("
          ",s),this.container.width(this.container_width()),this.is_multiple?this.container.html(this.get_multi_html()):this.container.html(this.get_single_html()),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior()},n.prototype.on_ready=function(){return this.form_field_jq.trigger("chosen:ready",{chosen:this})},n.prototype.register_observers=function(){return this.container.on("touchstart.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("touchend.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mousedown.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("mouseup.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mouseenter.chosen",function(t){return function(e){t.mouse_enter(e)}}(this)),this.container.on("mouseleave.chosen",function(t){return function(e){t.mouse_leave(e)}}(this)),this.search_results.on("mouseup.chosen",function(t){return function(e){t.search_results_mouseup(e)}}(this)),this.search_results.on("mouseover.chosen",function(t){return function(e){t.search_results_mouseover(e)}}(this)),this.search_results.on("mouseout.chosen",function(t){return function(e){t.search_results_mouseout(e)}}(this)),this.search_results.on("mousewheel.chosen DOMMouseScroll.chosen",function(t){return function(e){t.search_results_mousewheel(e)}}(this)),this.search_results.on("touchstart.chosen",function(t){return function(e){t.search_results_touchstart(e)}}(this)),this.search_results.on("touchmove.chosen",function(t){return function(e){t.search_results_touchmove(e)}}(this)),this.search_results.on("touchend.chosen",function(t){return function(e){t.search_results_touchend(e)}}(this)),this.form_field_jq.on("chosen:updated.chosen",function(t){return function(e){t.results_update_field(e)}}(this)),this.form_field_jq.on("chosen:activate.chosen",function(t){return function(e){t.activate_field(e)}}(this)),this.form_field_jq.on("chosen:open.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.form_field_jq.on("chosen:close.chosen",function(t){return function(e){t.close_field(e)}}(this)),this.search_field.on("blur.chosen",function(t){return function(e){t.input_blur(e)}}(this)),this.search_field.on("keyup.chosen",function(t){return function(e){t.keyup_checker(e)}}(this)),this.search_field.on("keydown.chosen",function(t){return function(e){t.keydown_checker(e)}}(this)),this.search_field.on("focus.chosen",function(t){return function(e){t.input_focus(e)}}(this)),this.search_field.on("cut.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.search_field.on("paste.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.is_multiple?this.search_choices.on("click.chosen",function(t){return function(e){t.choices_click(e)}}(this)):this.container.on("click.chosen",function(t){t.preventDefault()})},n.prototype.destroy=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.form_field_label.length>0&&this.form_field_label.off("click.chosen"),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},n.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field.disabled||this.form_field_jq.parents("fieldset").is(":disabled"),this.container.toggleClass("chosen-disabled",this.is_disabled),this.search_field[0].disabled=this.is_disabled,this.is_multiple||this.selected_item.off("focus.chosen",this.activate_field),this.is_disabled?this.close_field():this.is_multiple?void 0:this.selected_item.on("focus.chosen",this.activate_field)},n.prototype.container_mousedown=function(e){var s;if(!this.is_disabled)return!e||"mousedown"!==(s=e.type)&&"touchstart"!==s||this.results_showing||e.preventDefault(),null!=e&&t(e.target).hasClass("search-choice-close")?void 0:(this.active_field?this.is_multiple||!e||t(e.target)[0]!==this.selected_item[0]&&!t(e.target).parents("a.chosen-single").length||(e.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),t(this.container[0].ownerDocument).on("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},n.prototype.container_mouseup=function(t){if("ABBR"===t.target.nodeName&&!this.is_disabled)return this.results_reset(t)},n.prototype.search_results_mousewheel=function(t){var e;if(t.originalEvent&&(e=t.originalEvent.deltaY||-t.originalEvent.wheelDelta||t.originalEvent.detail),null!=e)return t.preventDefault(),"DOMMouseScroll"===t.type&&(e*=40),this.search_results.scrollTop(e+this.search_results.scrollTop())},n.prototype.blur_test=function(t){if(!this.active_field&&this.container.hasClass("chosen-container-active"))return this.close_field()},n.prototype.close_field=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale(),this.search_field.blur()},n.prototype.activate_field=function(){if(!this.is_disabled)return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},n.prototype.test_active_click=function(e){var s;return(s=t(e.target).closest(".chosen-container")).length&&this.container[0]===s[0]?this.active_field=!0:this.close_field()},n.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=i.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},n.prototype.result_do_highlight=function(t){var e,s,i,n,r;if(t.length){if(this.result_clear_highlight(),this.result_highlight=t,this.result_highlight.addClass("highlighted"),i=parseInt(this.search_results.css("maxHeight"),10),r=this.search_results.scrollTop(),n=i+r,s=this.result_highlight.position().top+this.search_results.scrollTop(),(e=s+this.result_highlight.outerHeight())>=n)return this.search_results.scrollTop(e-i>0?e-i:0);if(s0)return this.form_field_label.on("click.chosen",this.label_click_handler)},n.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},n.prototype.search_results_mouseup=function(e){var s;if((s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first()).length)return this.result_highlight=s,this.result_select(e),this.search_field.focus()},n.prototype.search_results_mouseover=function(e){var s;if(s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first())return this.result_do_highlight(s)},n.prototype.search_results_mouseout=function(e){if(t(e.target).hasClass("active-result")||t(e.target).parents(".active-result").first())return this.result_clear_highlight()},n.prototype.choice_build=function(e){var s,i;return s=t("
        • ",{"class":"search-choice"}).html(""+this.choice_label(e)+""),e.disabled?s.addClass("search-choice-disabled"):((i=t("",{"class":"search-choice-close","data-option-array-index":e.array_index})).on("click.chosen",function(t){return function(e){return t.choice_destroy_link_click(e)}}(this)),s.append(i)),this.search_container.before(s)},n.prototype.choice_destroy_link_click=function(e){if(e.preventDefault(),e.stopPropagation(),!this.is_disabled)return this.choice_destroy(t(e.target))},n.prototype.choice_destroy=function(t){if(this.result_deselect(t[0].getAttribute("data-option-array-index")))return this.active_field?this.search_field.focus():this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.get_search_field_value().length<1&&this.results_hide(),t.parents("li").first().remove(),this.search_field_scale()},n.prototype.results_reset=function(){if(this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.trigger_form_field_change(),this.active_field)return this.results_hide()},n.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},n.prototype.result_select=function(t){var e,s;if(this.result_highlight)return e=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?e.removeClass("active-result"):this.reset_single_select_options(),e.addClass("result-selected"),s=this.results_data[e[0].getAttribute("data-option-array-index")],s.selected=!0,this.form_field.options[s.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(s):this.single_set_selected_text(this.choice_label(s)),this.is_multiple&&(!this.hide_results_on_select||t.metaKey||t.ctrlKey)?t.metaKey||t.ctrlKey?this.winnow_results({skip_highlight:!0}):(this.search_field.val(""),this.winnow_results()):(this.results_hide(),this.show_search_field_default()),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.trigger_form_field_change({selected:this.form_field.options[s.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,t.preventDefault(),this.search_field_scale())},n.prototype.single_set_selected_text=function(t){return null==t&&(t=this.default_text),t===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").html(t)},n.prototype.result_deselect=function(t){var e;return e=this.results_data[t],!this.form_field.options[e.options_index].disabled&&(e.selected=!1,this.form_field.options[e.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.trigger_form_field_change({deselected:this.form_field.options[e.options_index].value}),this.search_field_scale(),!0)},n.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect)return this.selected_item.find("abbr").length||this.selected_item.find("span").first().after(''),this.selected_item.addClass("chosen-single-with-deselect")},n.prototype.get_search_field_value=function(){return this.search_field.val()},n.prototype.get_search_text=function(){return t.trim(this.get_search_field_value())},n.prototype.escape_html=function(e){return t("
          ").text(e).html()},n.prototype.winnow_results_set_highlight=function(){var t,e;if(e=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),null!=(t=e.length?e.first():this.search_results.find(".active-result").first()))return this.result_do_highlight(t)},n.prototype.no_results=function(t){var e;return e=this.get_no_results_html(t),this.search_results.append(e),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},n.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},n.prototype.keydown_arrow=function(){var t;return this.results_showing&&this.result_highlight?(t=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(t):void 0:this.results_show()},n.prototype.keyup_arrow=function(){var t;return this.results_showing||this.is_multiple?this.result_highlight?(t=this.result_highlight.prevAll("li.active-result")).length?this.result_do_highlight(t.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight()):void 0:this.results_show()},n.prototype.keydown_backstroke=function(){var t;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(t=this.search_container.siblings("li.search-choice").last()).length&&!t.hasClass("search-choice-disabled")?(this.pending_backstroke=t,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0},n.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},n.prototype.search_field_scale=function(){var e,s,i,n,r,o,h;if(this.is_multiple){for(r={position:"absolute",left:"-1000px",top:"-1000px",display:"none",whiteSpace:"pre"},s=0,i=(o=["fontSize","fontStyle","fontWeight","fontFamily","lineHeight","textTransform","letterSpacing"]).length;s").css(r)).text(this.get_search_field_value()),t("body").append(e),h=e.width()+25,e.remove(),this.container.is(":visible")&&(h=Math.min(this.container.outerWidth()-10,h)),this.search_field.width(h)}},n.prototype.trigger_form_field_change=function(t){return this.form_field_jq.trigger("input",t),this.form_field_jq.trigger("change",t)},n}()}).call(this); \ No newline at end of file diff --git a/web/skins/classic/js/chosen/chosen.min.css b/web/skins/classic/js/chosen/chosen.min.css index 779d83d91..1c68ebb1c 100644 --- a/web/skins/classic/js/chosen/chosen.min.css +++ b/web/skins/classic/js/chosen/chosen.min.css @@ -2,10 +2,10 @@ Chosen, a Select Box Enhancer for jQuery and Prototype by Patrick Filler for Harvest, http://getharvest.com -Version 1.8.2 +Version 1.8.7 Full source at https://github.com/harvesthq/chosen -Copyright (c) 2011-2017 Harvest http://getharvest.com +Copyright (c) 2011-2018 Harvest http://getharvest.com MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md This file is generated by `grunt build`, do not edit it by hand. -*/.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.chosen-container *{-webkit-box-sizing:border-box;box-sizing:border-box}.chosen-container .chosen-drop{position:absolute;top:100%;z-index:1010;width:100%;border:1px solid #aaa;border-top:0;background:#fff;-webkit-box-shadow:0 4px 5px rgba(0,0,0,.15);box-shadow:0 4px 5px rgba(0,0,0,.15);clip:rect(0,0,0,0)}.chosen-container.chosen-with-drop .chosen-drop{clip:auto}.chosen-container a{cursor:pointer}.chosen-container .chosen-single .group-name,.chosen-container .search-choice .group-name{margin-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-weight:400;color:#999}.chosen-container .chosen-single .group-name:after,.chosen-container .search-choice .group-name:after{content:":";padding-left:2px;vertical-align:top}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:25px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),to(#f4f4f4));background:linear-gradient(#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;-webkit-box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:url(chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;clip:rect(0,0,0,0)}.chosen-container .chosen-results{color:#444;position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;word-wrap:break-word;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{color:#777;display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;margin:0;padding:0 5px;width:100%;height:auto;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(1%,#eee),color-stop(15%,#fff));background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:0;height:25px;outline:0;border:0!important;background:0 0!important;-webkit-box-shadow:none;box-shadow:none;color:#999;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0;width:25px}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 5px 3px 0;padding:3px 20px 3px 5px;border:1px solid #aaa;max-width:100%;border-radius:3px;background-color:#eee;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),to(#eee));background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-size:100% 19px;background-repeat:repeat-x;background-clip:padding-box;-webkit-box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice span{word-wrap:break-word}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),to(#eee));background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;-webkit-box-shadow:0 0 5px rgba(0,0,0,.3);box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;border-bottom-right-radius:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#eee),color-stop(80%,#fff));background-image:linear-gradient(#eee 20%,#fff 80%);-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:none;background:0 0}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;-webkit-box-shadow:0 0 5px rgba(0,0,0,.3);box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#222!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:none}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:url(chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi),only screen and (min-resolution:1.5dppx){.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span,.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container-single .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-rtl .chosen-search input[type=text]{background-image:url(chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}} \ No newline at end of file +*/.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.chosen-container *{-webkit-box-sizing:border-box;box-sizing:border-box}.chosen-container .chosen-drop{position:absolute;top:100%;z-index:1010;width:100%;border:1px solid #aaa;border-top:0;background:#fff;-webkit-box-shadow:0 4px 5px rgba(0,0,0,.15);box-shadow:0 4px 5px rgba(0,0,0,.15);clip:rect(0,0,0,0);-webkit-clip-path:inset(100% 100%);clip-path:inset(100% 100%)}.chosen-container.chosen-with-drop .chosen-drop{clip:auto;-webkit-clip-path:none;clip-path:none}.chosen-container a{cursor:pointer}.chosen-container .chosen-single .group-name,.chosen-container .search-choice .group-name{margin-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-weight:400;color:#999}.chosen-container .chosen-single .group-name:after,.chosen-container .search-choice .group-name:after{content:":";padding-left:2px;vertical-align:top}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:25px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),to(#f4f4f4));background:linear-gradient(#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;-webkit-box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:url(chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;clip:rect(0,0,0,0);-webkit-clip-path:inset(100% 100%);clip-path:inset(100% 100%)}.chosen-container .chosen-results{color:#444;position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;word-wrap:break-word;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{color:#777;display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;margin:0;padding:0 5px;width:100%;height:auto;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(1%,#eee),color-stop(15%,#fff));background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:0;height:25px;outline:0;border:0!important;background:0 0!important;-webkit-box-shadow:none;box-shadow:none;color:#999;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0;width:25px}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 5px 3px 0;padding:3px 20px 3px 5px;border:1px solid #aaa;max-width:100%;border-radius:3px;background-color:#eee;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),to(#eee));background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-size:100% 19px;background-repeat:repeat-x;background-clip:padding-box;-webkit-box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice span{word-wrap:break-word}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),to(#eee));background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;-webkit-box-shadow:0 0 5px rgba(0,0,0,.3);box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;border-bottom-right-radius:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(20%,#eee),color-stop(80%,#fff));background-image:linear-gradient(#eee 20%,#fff 80%);-webkit-box-shadow:0 1px 0 #fff inset;box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:none;background:0 0}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;-webkit-box-shadow:0 0 5px rgba(0,0,0,.3);box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#222!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:none}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:url(chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi),only screen and (min-resolution:1.5dppx){.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span,.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container-single .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-rtl .chosen-search input[type=text]{background-image:url(chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}} \ No newline at end of file From 63199289ad6f9da391344794a447e52a92c01f34 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 24 Dec 2018 09:38:55 -0500 Subject: [PATCH 215/240] Change depth function to be 0-based. --- web/includes/Group.php | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/web/includes/Group.php b/web/includes/Group.php index 6c8338a55..82c1daba9 100644 --- a/web/includes/Group.php +++ b/web/includes/Group.php @@ -120,12 +120,13 @@ class Group { } else { return null; } - } + } # end function find_one public function delete() { if ( array_key_exists('Id', $this) ) { - dbQuery( 'DELETE FROM Groups_Monitors WHERE GroupId=?', array($this->{'Id'}) ); - dbQuery( 'DELETE FROM Groups WHERE Id=?', array($this->{'Id'}) ); + dbQuery('DELETE FROM Groups_Monitors WHERE GroupId=?', array($this->{'Id'})); + dbQuery('UPDATE Groups SET ParentId=NULL WHERE ParentId=?', array($this->{'Id'})); + dbQuery('DELETE FROM Groups WHERE Id=?', array($this->{'Id'})); if ( isset($_COOKIE['zmGroup']) ) { if ( $this->{'Id'} == $_COOKIE['zmGroup'] ) { unset($_COOKIE['zmGroup']); @@ -150,16 +151,17 @@ class Group { $this->{$k} = $v; } } - } + } # end function set + public function depth( $new = null ) { if ( isset($new) ) { $this->{'depth'} = $new; } - if ( ! array_key_exists('depth', $this) or ($this->{'depth'} == null) ) { - $this->{'depth'} = 1; + if ( !array_key_exists('depth', $this) or ($this->{'depth'} === null) ) { + $this->{'depth'} = 0; if ( $this->{'ParentId'} != null ) { $Parent = Group::find_one(array('Id'=>$this->{'ParentId'})); - $this->{'depth'} += $Parent->depth(); + $this->{'depth'} += $Parent->depth()+1; } } return $this->{'depth'}; @@ -210,7 +212,7 @@ class Group { $children[$Group->ParentId()] = array(); $children[$Group->ParentId()][] = $Group; } - } + } # end foreach function get_options($Group) { global $children; @@ -221,7 +223,8 @@ class Group { } } return $options; - } + } # end function get_options + $group_options = array(); foreach ( $Groups as $id=>$Group ) { if ( ! $Group->ParentId() ) { @@ -229,7 +232,7 @@ class Group { } } return $group_options; - } + } # end function get_dropdown_options public static function get_group_sql($group_id) { $groupSql = ''; From e0cae5709f76f491f1f54b6e67870c4bf4067f45 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 24 Dec 2018 09:39:40 -0500 Subject: [PATCH 216/240] Group::find is now more powerful so we can just use it to return all Groups to be deleted --- web/includes/actions.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index 84b6c4d01..5bb48debb 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -642,16 +642,11 @@ if ( canEdit('Groups') ) { $refreshParent = true; } else if ( $action == 'delete' ) { if ( !empty($_REQUEST['gid']) ) { - if ( is_array($_REQUEST['gid']) ) { - foreach ( $_REQUEST['gid'] as $gid ) { - $Group = new Group($gid); - $Group->delete(); - } - } else { - $Group = new Group($_REQUEST['gid'] ); + foreach ( Group::find(array('Id'=>$_REQUEST['gid'])) as $Group ) { $Group->delete(); } } + $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=groups'; $refreshParent = true; } # end if action } // end if can edit groups From 68adc289fee02086f9f6d5b4937d77b852639822 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 24 Dec 2018 09:40:23 -0500 Subject: [PATCH 217/240] Fix colspan count now that depth is zero-based --- web/skins/classic/views/groups.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/groups.php b/web/skins/classic/views/groups.php index fb383026d..2e3c4faae 100644 --- a/web/skins/classic/views/groups.php +++ b/web/skins/classic/views/groups.php @@ -28,7 +28,7 @@ $group_id = 0; $max_depth = 0; $Groups = array(); -foreach ( Group::find( ) as $Group ) { +foreach ( Group::find() as $Group ) { $Groups[$Group->Id()] = $Group; } @@ -53,7 +53,7 @@ xhtmlHeaders(__FILE__, translate('Groups')); - + From e0a9c4a21e5082ba74910d8ee2062bb8f6019aee Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 24 Dec 2018 11:23:58 -0500 Subject: [PATCH 218/240] fix event popup detection --- web/skins/classic/views/event.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index 3312a8d07..ce27dfcf8 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -95,7 +95,7 @@ $connkey = generateConnKey(); $focusWindow = true; -$popup = ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] = 1)); +$popup = ((isset($_REQUEST['popup'])) && ($_REQUEST['popup'] == 1)); xhtmlHeaders(__FILE__, translate('Event') ); ?> From 55e0d82f208f9b9e70a5d95b8cc0715c432cdb2c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 24 Dec 2018 11:30:22 -0500 Subject: [PATCH 219/240] spacing --- src/zm_videostore.cpp | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 400ac7fde..cb7bac722 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -908,15 +908,15 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { * to flush it. */ int data_present; - if ((ret = avcodec_decode_audio4(audio_in_ctx, in_frame, - &data_present, ipkt)) < 0) { - Error("Could not decode frame (error '%s')\n", + if ( (ret = avcodec_decode_audio4( + audio_in_ctx, in_frame, &data_present, ipkt)) < 0 ) { + Error("Could not decode frame (error '%s')", av_make_error_string(ret).c_str()); dumpPacket(ipkt); av_frame_free(&in_frame); return 0; } - if (!data_present) { + if ( !data_present ) { Debug(2, "Not ready to transcode a frame yet."); return 0; } @@ -925,44 +925,40 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { // Resample the in into the audioSampleBuffer until we proceed the whole // decoded data - #if defined(HAVE_LIBSWRESAMPLE) Debug(2, "Converting %d to %d samples", in_frame->nb_samples, out_frame->nb_samples); - if ((ret = swr_convert(resample_ctx, + if ( + #if defined(HAVE_LIBSWRESAMPLE) + (ret = swr_convert(resample_ctx, out_frame->data, frame_size, (const uint8_t**)in_frame->data, - in_frame->nb_samples)) < 0) { - Error("Could not resample frame (error '%s')\n", - av_make_error_string(ret).c_str()); - av_frame_unref(in_frame); - return 0; - } + in_frame->nb_samples)) #else #if defined(HAVE_LIBAVRESAMPLE) - if ((ret = - avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data, - 0, in_frame->nb_samples)) < 0) { - Error("Could not resample frame (error '%s')\n", + (ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data, + 0, in_frame->nb_samples)) + #endif + #endif + < 0) { + Error("Could not resample frame (error '%s')", av_make_error_string(ret).c_str()); av_frame_unref(in_frame); return 0; } - #endif - #endif av_frame_unref(in_frame); #if defined(HAVE_LIBAVRESAMPLE) int samples_available = avresample_available(resample_ctx); - if (samples_available < frame_size) { + if ( samples_available < frame_size ) { Debug(1, "Not enough samples yet (%d)", samples_available); return 0; } Debug(3, "Output_frame samples (%d)", out_frame->nb_samples); // Read a frame audio data from the resample fifo - if (avresample_read(resample_ctx, out_frame->data, frame_size) != + if ( avresample_read(resample_ctx, out_frame->data, frame_size) != frame_size) { - Warning("Error reading resampled audio: "); + Warning("Error reading resampled audio:"); return 0; } #endif From 5f9a113da1ea59f839c087a7172874ffcd210578 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 26 Dec 2018 10:34:01 -0600 Subject: [PATCH 220/240] redirect to montage rather than montagereview --- web/includes/actions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index 5bb48debb..2ae7fdc2a 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -670,7 +670,7 @@ if ( canEdit('System') ) { $_SESSION['zmMontageLayout'] = $Layout->Id(); setcookie('zmMontageLayout', $Layout->Id(), 1); session_write_close(); - $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montagereview'; + $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montage'; } // end if save } else if ( $_REQUEST['object'] == 'server' ) { From b87ae53a83f999b414667ac3f8608c4338a6d477 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Dec 2018 11:50:43 -0500 Subject: [PATCH 221/240] merge debug lines and correct spacing --- src/zm_monitor.cpp | 100 ++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 5a513dbf8..df8f75c54 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -483,9 +483,14 @@ Monitor::Monitor( event = 0; - Debug( 1, "Monitor %s has function %d", name, function ); - Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d, LBS = %d", name, label_format, label_coord.X(), label_coord.Y(), label_size ); - Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, ARBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, alarm_ref_blend_perc, track_motion ); + Debug(1, "Monitor %s has function %d,\n" + "label format = '%s', label X = %d, label Y = %d, label size = %d,\n" + "image buffer count = %d, warmup count = %d, pre-event count = %d, post-event count = %d, alarm frame count = %d,\n" + "fps report interval = %d, ref blend percentage = %d, alarm ref blend percentage = %d, track motion = %d", + name, function, + label_format, label_coord.X(), label_coord.Y(), label_size, + image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, + fps_report_interval, ref_blend_perc, alarm_ref_blend_perc, track_motion ); //Set video recording flag for event start constructor and easy reference in code videoRecording = ((GetOptVideoWriter() == H264PASSTHROUGH) && camera->SupportsNativeVideo()); @@ -494,7 +499,6 @@ Monitor::Monitor( linked_monitors = 0; if ( purpose == ANALYSIS ) { -Debug(2,"last_write_index(%d), last_write_time(%d)", shared_data->last_write_index, shared_data->last_write_time ); while( ( shared_data->last_write_index == (unsigned int)image_buffer_count ) && @@ -502,80 +506,77 @@ Debug(2,"last_write_index(%d), last_write_time(%d)", shared_data->last_write_ind && ( !zm_terminate ) ) { - Debug(1, "Waiting for capture daemon"); + Debug(1, "Waiting for capture daemon last_write_index(%d), last_write_time(%d)", + shared_data->last_write_index, shared_data->last_write_time ); sleep(1); } ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize()); adaptive_skip = true; - ReloadLinkedMonitors( p_linked_monitors ); - } + ReloadLinkedMonitors(p_linked_monitors); + } // end if purpose == ANALYSIS } // Monitor::Monitor - bool Monitor::connect() { Debug(3, "Connecting to monitor. Purpose is %d", purpose ); #if ZM_MEM_MAPPED - snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id ); - map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); + snprintf(mem_file, sizeof(mem_file), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id); + map_fd = open(mem_file, O_RDWR|O_CREAT, (mode_t)0600); if ( map_fd < 0 ) { - Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); + Fatal("Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno)); } else { - Debug(3, "Success opening mmap file at (%s)", mem_file ); + Debug(3, "Success opening mmap file at (%s)", mem_file); } struct stat map_stat; - if ( fstat( map_fd, &map_stat ) < 0 ) - Fatal( "Can't stat memory map file %s: %s, is the zmc process for this monitor running?", mem_file, strerror(errno) ); + if ( fstat(map_fd, &map_stat) < 0 ) + Fatal("Can't stat memory map file %s: %s, is the zmc process for this monitor running?", mem_file, strerror(errno)); if ( map_stat.st_size != mem_size ) { if ( purpose == CAPTURE ) { // Allocate the size - if ( ftruncate( map_fd, mem_size ) < 0 ) { - Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); + if ( ftruncate(map_fd, mem_size) < 0 ) { + Fatal("Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno)); } } else if ( map_stat.st_size == 0 ) { - Error( "Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size ); + Error("Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size); return false; } else { - Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + Error("Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size); return false; } } - Debug(3, "MMap file size is %ld", map_stat.st_size ); + Debug(3, "MMap file size is %ld", map_stat.st_size); #ifdef MAP_LOCKED - mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 ); + mem_ptr = (unsigned char *)mmap(NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0); if ( mem_ptr == MAP_FAILED ) { if ( errno == EAGAIN ) { - Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size ); - + Debug(1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size); #endif - mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); - Debug( 1, "Mapped file %s (%d bytes) to unlocked memory", mem_file, mem_size ); + mem_ptr = (unsigned char *)mmap(NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0); + Debug(1, "Mapped file %s (%d bytes) to unlocked memory", mem_file, mem_size); #ifdef MAP_LOCKED } else { - Error( "Unable to map file %s (%d bytes) to locked memory (%s)", mem_file, mem_size , strerror(errno) ); + Error("Unable to map file %s (%d bytes) to locked memory (%s)", mem_file, mem_size, strerror(errno)); } } #endif if ( mem_ptr == MAP_FAILED ) - Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); + Fatal("Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno); if ( mem_ptr == NULL ) { - Error( "mmap gave a null address:" ); + Error("mmap gave a null address:"); } else { - Debug(3, "mmapped to %p", mem_ptr ); + Debug(3, "mmapped to %p", mem_ptr); } #else // ZM_MEM_MAPPED - shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 ); + shm_id = shmget((config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700); if ( shm_id < 0 ) { - Error( "Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); - exit( -1 ); + Fatal("Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); } mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); if ( mem_ptr < (void *)0 ) { - Error( "Can't shmat: %s", strerror(errno)); - exit( -1 ); + Fatal("Can't shmat: %s", strerror(errno)); } #endif // ZM_MEM_MAPPED shared_data = (SharedData *)mem_ptr; @@ -584,13 +585,12 @@ bool Monitor::connect() { struct timeval *shared_timestamps = (struct timeval *)((char *)video_store_data + sizeof(VideoStoreData)); unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval))); - if ( ((unsigned long)shared_images % 64) != 0 ) { /* Align images buffer to nearest 64 byte boundary */ Debug(3,"Aligning shared memory images to the next 64 byte boundary"); shared_images = (uint8_t*)((unsigned long)shared_images + (64 - ((unsigned long)shared_images % 64))); } - Debug(3, "Allocating %d image buffers", image_buffer_count ); + Debug(3, "Allocating %d image buffers", image_buffer_count); image_buffer = new Snapshot[image_buffer_count]; for ( int i = 0; i < image_buffer_count; i++ ) { image_buffer[i].timestamp = &(shared_timestamps[i]); @@ -615,15 +615,15 @@ bool Monitor::connect() { *pre_event_buffer[i].timestamp = {0,0}; pre_event_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); } - } + } // end if max_analysis_fps timestamps = new struct timeval *[pre_event_count]; images = new Image *[pre_event_count]; last_signal = shared_data->signal; - } + } // end if purpose == ANALYSIS Debug(3, "Success connecting"); return true; -} +} // end Monitor::connect Monitor::~Monitor() { if ( n_linked_monitors ) { @@ -695,31 +695,29 @@ Monitor::~Monitor() { } #if ZM_MEM_MAPPED - if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 ) - Error( "Can't msync: %s", strerror(errno) ); - if ( munmap( mem_ptr, mem_size ) < 0 ) - Fatal( "Can't munmap: %s", strerror(errno) ); + if ( msync(mem_ptr, mem_size, MS_SYNC) < 0 ) + Error("Can't msync: %s", strerror(errno)); + if ( munmap(mem_ptr, mem_size) < 0 ) + Fatal("Can't munmap: %s", strerror(errno)); close( map_fd ); if ( purpose == CAPTURE ) { // How about we store this in the object on instantiation so that we don't have to do this again. char mmap_path[PATH_MAX] = ""; - snprintf( mmap_path, sizeof(mmap_path), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id ); + snprintf(mmap_path, sizeof(mmap_path), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id); - if ( unlink( mmap_path ) < 0 ) { - Warning( "Can't unlink '%s': %s", mmap_path, strerror(errno) ); + if ( unlink(mmap_path) < 0 ) { + Warning("Can't unlink '%s': %s", mmap_path, strerror(errno)); } } #else // ZM_MEM_MAPPED struct shmid_ds shm_data; - if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) { - Error( "Can't shmctl: %s", strerror(errno) ); - exit( -1 ); + if ( shmctl(shm_id, IPC_STAT, &shm_data) < 0 ) { + Fatal("Can't shmctl: %s", strerror(errno)); } if ( shm_data.shm_nattch <= 1 ) { - if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) { - Error( "Can't shmctl: %s", strerror(errno) ); - exit( -1 ); + if ( shmctl(shm_id, IPC_RMID, 0) < 0 ) { + Fatal("Can't shmctl: %s", strerror(errno)); } } #endif // ZM_MEM_MAPPED From db6d94385425a7ec33d8f261acc76b01b8cb3504 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Dec 2018 11:53:21 -0500 Subject: [PATCH 222/240] If failure in connect, close the fd before returning --- src/zm_monitor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index df8f75c54..4c5c9f7b2 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -540,9 +540,13 @@ bool Monitor::connect() { } } else if ( map_stat.st_size == 0 ) { Error("Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size); + close(map_fd); + map_fd = -1; return false; } else { Error("Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size); + close(map_fd); + map_fd = -1; return false; } } From c017219a1e4983bdc1b7202ff36913c1a160bc82 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Dec 2018 12:22:06 -0500 Subject: [PATCH 223/240] use do instead of many lines of dbi. Cleanup logic around command detection --- scripts/zmpkg.pl.in | 81 ++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 46 deletions(-) diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in index 2d6593619..af8e9e8fc 100644 --- a/scripts/zmpkg.pl.in +++ b/scripts/zmpkg.pl.in @@ -54,35 +54,35 @@ if ( $command eq 'version' ) { my $state; my $dbh = zmDbConnect(); -Info("Command: $command"); -if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) { - if ( $command ) { -# Check to see if it's a valid run state - my $sql = 'SELECT * FROM States WHERE Name=?'; - my $sth = $dbh->prepare_cached($sql) - or Fatal("Can't prepare '$sql': ".$dbh->errstr()); - my $res = $sth->execute($command) - or Fatal("Can't execute: ".$sth->errstr()); - if ( $state = $sth->fetchrow_hashref() ) { - #$state->{Name} = $command; - $state->{Definitions} = []; - foreach( split(',', $state->{Definition}) ) { - my ( $id, $function, $enabled ) = split(':', $_); - push( @{$state->{Definitions}}, - { Id=>$id, Function=>$function, Enabled=>$enabled } - ); - } - $store_state = $command; # PP - Remember the name that was passed to search in DB - $command = 'state'; - } else { - $command = undef; +Debug("Command: $command"); +if ( $command and ( $command !~ /^(?:start|stop|restart|status|logrot|version)$/ ) ) { + # Check to see if it's a valid run state + my $sql = 'SELECT * FROM States WHERE Name=?'; + my $sth = $dbh->prepare_cached($sql) + or Fatal("Can't prepare '$sql': ".$dbh->errstr()); + my $res = $sth->execute($command) + or Fatal("Can't execute: ".$sth->errstr()); + if ( $state = $sth->fetchrow_hashref() ) { + #$state->{Name} = $command; + $state->{Definitions} = []; + foreach( split(',', $state->{Definition}) ) { + my ( $id, $function, $enabled ) = split(':', $_); + push( @{$state->{Definitions}}, + { Id=>$id, Function=>$function, Enabled=>$enabled } + ); } + $store_state = $command; # PP - Remember the name that was passed to search in DB + $command = 'state'; + } else { + $command = undef; } - if ( !$command ) { - pod2usage(-exitstatus => -1); - } + $sth->finish(); } # end if not one of the usual commands +if ( !$command ) { + pod2usage(-exitstatus => -1); +} + # PP - Sane state check Debug("StartisActiveSSantiyCheck"); isActiveSanityCheck(); @@ -314,20 +314,14 @@ sub isActiveSanityCheck { if ( $sth->rows != 1 ) { # PP - no row, or too many rows. Either case is an error - Info( 'Fixing States table - either no default state or duplicate default states' ); + Info('Fixing States table - either no default state or duplicate default states'); if ( $sth->rows ) { - $sql = q`DELETE FROM States WHERE Name='default'`; - $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - $res = $sth->execute() - or Fatal( "Can't execute: ".$sth->errstr() ); + $dbh->do(q`DELETE FROM States WHERE Name='default'`) or Fatal("Can't execute: ".$dbh->errstr()); } - $sql = q`INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');`; - $sth = $dbh->prepare_cached($sql) - or Fatal("Can't prepare '$sql': ".$dbh->errstr()); - $res = $sth->execute() - or Fatal("Can't execute: ".$sth->errstr()); + $dbh->do(q`INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');`) + or Fatal("Can't execute: ".$dbh->errstr()); } + $sth->finish(); # PP - Now make sure no two states have IsActive=1 $sql = 'SELECT Name FROM States WHERE IsActive = 1'; @@ -339,22 +333,17 @@ sub isActiveSanityCheck { if ( $sth->rows != 1 ) { Info('Fixing States table so only one run state is active'); resetStates(); - $sql = q`UPDATE States SET IsActive=1 WHERE Name='default'`; - $sth = $dbh->prepare_cached($sql) - or Fatal("Can't prepare '$sql': ".$dbh->errstr()); - $res = $sth->execute() - or Fatal("Can't execute: ".$sth->errstr()); + $dbh->do(q`UPDATE States SET IsActive=1 WHERE Name='default'`) + or Fatal("Can't execute: ".$dbh->errstr()); } + $sth->finish(); } # end sub isActiveSanityCheck # PP - zeroes out isActive for all states sub resetStates { $dbh = zmDbConnect() if ! $dbh; - my $sql = 'UPDATE States SET IsActive=0'; - my $sth = $dbh->prepare_cached($sql) - or Fatal("Can't prepare '$sql': ".$dbh->errstr()); - my $res = $sth->execute() - or Fatal("Can't execute: ".$sth->errstr()); + $dbh->do('UPDATE States SET IsActive=0') + or Fatal("Can't execute: ".$dbh->errstr()); } sub systemdRunning { From 08e5166bcb26e436287d67bc0662079695fa319f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Dec 2018 12:24:50 -0500 Subject: [PATCH 224/240] remove quotes around state in command documentation. --- scripts/zmpkg.pl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in index af8e9e8fc..167943952 100644 --- a/scripts/zmpkg.pl.in +++ b/scripts/zmpkg.pl.in @@ -391,7 +391,7 @@ zmpkg.pl - ZoneMinder Package Control Script =head1 SYNOPSIS -zmpkg.pl {start|stop|restart|status|logrot|'state'|version} +zmpkg.pl {start|stop|restart|status|logrot|state|version} =head1 DESCRIPTION From 32c88a3a41a3cf41adef46f580b15cc032336f89 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Dec 2018 13:50:17 -0500 Subject: [PATCH 225/240] Update status as well as fps when updating fps --- src/zm_monitor.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 4c5c9f7b2..30feecfe8 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2488,8 +2488,13 @@ int Monitor::Capture() { fps = new_fps; db_mutex.lock(); static char sql[ZM_SQL_SML_BUFSIZ]; + // The reason we update the Status as well is because if mysql restarts, the Monitor_Status table is lost, + // and nothing else will update the status until zmc restarts. Since we are successfully capturing we can + // assume that we are connected snprintf(sql, sizeof(sql), - "INSERT INTO Monitor_Status (MonitorId,CaptureFPS,CaptureBandwidth) VALUES (%d, %.2lf,%u) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf, CaptureBandwidth=%u", + "INSERT INTO Monitor_Status (MonitorId,CaptureFPS,CaptureBandwidth,Status) " + "VALUES (%d, %.2lf, %u, 'Connected') ON DUPLICATE KEY UPDATE " + "CaptureFPS = %.2lf, CaptureBandwidth=%u, Status='Connected'", id, fps, new_capture_bandwidth, fps, new_capture_bandwidth); if ( mysql_query(&dbconn, sql) ) { Error("Can't run query: %s", mysql_error(&dbconn)); From 4937a68650aeafaff78559f27818616ecd4dfbce Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Dec 2018 14:27:43 -0500 Subject: [PATCH 226/240] Update area when editing x and y coords --- web/skins/classic/views/js/zone.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/skins/classic/views/js/zone.js b/web/skins/classic/views/js/zone.js index bfcd91943..d42b3d807 100644 --- a/web/skins/classic/views/js/zone.js +++ b/web/skins/classic/views/js/zone.js @@ -347,6 +347,7 @@ function updateX( index ) { zone['Points'][index].x = x; var Point = $('zonePoly').points.getItem(index); Point.x = x; + updateArea(); } function updateY( index ) { @@ -359,6 +360,7 @@ function updateY( index ) { zone['Points'][index].y = y; var Point = $('zonePoly').points.getItem(index); Point.y = y; + updateArea(); } function saveChanges( element ) { From 101f24feb5b1679254a1dbbc77eb172c4e5f8eb8 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Dec 2018 14:28:14 -0500 Subject: [PATCH 227/240] Update area when editing x and y coords (#2366) --- web/skins/classic/views/js/zone.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/skins/classic/views/js/zone.js b/web/skins/classic/views/js/zone.js index bfcd91943..d42b3d807 100644 --- a/web/skins/classic/views/js/zone.js +++ b/web/skins/classic/views/js/zone.js @@ -347,6 +347,7 @@ function updateX( index ) { zone['Points'][index].x = x; var Point = $('zonePoly').points.getItem(index); Point.x = x; + updateArea(); } function updateY( index ) { @@ -359,6 +360,7 @@ function updateY( index ) { zone['Points'][index].y = y; var Point = $('zonePoly').points.getItem(index); Point.y = y; + updateArea(); } function saveChanges( element ) { From c128998c2080642317d4e34cb5eed5fc3edb88b8 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Thu, 27 Dec 2018 18:16:52 -0600 Subject: [PATCH 228/240] Update redhat.rst --- docs/installationguide/redhat.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installationguide/redhat.rst b/docs/installationguide/redhat.rst index 12d9ed769..71b4f5278 100644 --- a/docs/installationguide/redhat.rst +++ b/docs/installationguide/redhat.rst @@ -197,7 +197,7 @@ If you have previsouly cloned the ZoneMinder git repo and wish to update it to t :: - cd ~\ZoneMinder + cd ~/ZoneMinder git pull origin master Get the crud submodule tarball: @@ -210,14 +210,14 @@ At this point, you can make changes to the source code. Depending on what you wa :: - cd ~\ZoneMinder + cd ~/ZoneMinder git checkout -b mynewbranch Again, depending on what you want to do with those changes, you may want to commit your changes: :: - cd ~\ZoneMinder + cd ~/ZoneMinder git add . git commit @@ -231,7 +231,7 @@ Scroll down until you see the Version field. Note the value, which will be in th :: - cd ~\ZoneMinder + cd ~/ZoneMinder git archive --prefix=ZoneMinder-1.31.1/ -o ~/rpmbuild/SOURCES/zoneminder-1.31.1.tar.gz HEAD Replace "1.31.1" with the Version shown in the rpm specfile. @@ -240,7 +240,7 @@ From the root of the local ZoneMinder git repo, execute the following: :: - cd ~\ZoneMinder + cd ~/ZoneMinder rpmbuild -bs --nodeps distros/redhat/zoneminder.spec This step will create a source rpm and it will tell you where it was saved. For example: From 6e7ecf4e89eed6d4a3e57bc865ef9352a9a5b9bf Mon Sep 17 00:00:00 2001 From: Jonathan Meredith <35303639+jimender2@users.noreply.github.com> Date: Thu, 27 Dec 2018 22:20:24 -0500 Subject: [PATCH 229/240] Fix spelling mistake Changed his to this --- docs/userguide/options/options_images.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/options/options_images.rst b/docs/userguide/options/options_images.rst index 3e8598425..1b17d8336 100644 --- a/docs/userguide/options/options_images.rst +++ b/docs/userguide/options/options_images.rst @@ -23,7 +23,7 @@ MPEG_LIVE_FORMAT - When using MPEG mode ZoneMinder can output live video. Howeve MPEG_REPLAY_FORMAT - When using MPEG mode ZoneMinder can replay events in encoded video format. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player and 'mpg', or 'avi' etc should work under Linux. If you know any more then please let me know! If this option is left blank then live streams will revert to being in motion jpeg format -RAND_STREAM - Some browsers can cache the streams used by ZoneMinder. In order to prevent his a harmless random string can be appended to the url to make each invocation of the stream appear unique. +RAND_STREAM - Some browsers can cache the streams used by ZoneMinder. In order to prevent this a harmless random string can be appended to the url to make each invocation of the stream appear unique. OPT_CAMBOZOLA - Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed. From 265a73ab29402f821da16c7cc4583c5b2e04fce5 Mon Sep 17 00:00:00 2001 From: Jonathan Meredith <35303639+jimender2@users.noreply.github.com> Date: Thu, 27 Dec 2018 22:26:07 -0500 Subject: [PATCH 230/240] Spelling mistake fix Changed his to this --- scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 27d993894..846a62f82 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -659,7 +659,7 @@ our @options = ( description => 'Add a random string to prevent caching of streams', help => q` Some browsers can cache the streams used by ZoneMinder. In - order to prevent his a harmless random string can be appended + order to prevent this a harmless random string can be appended to the url to make each invocation of the stream appear unique. `, type => $types{boolean}, From fb37fc48e19eb644e41fbde28eebe831cc8aa05a Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 28 Dec 2018 09:38:39 -0600 Subject: [PATCH 231/240] update viewImagePatch (#2370) --- web/includes/functions.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 8baf30921..f4a9b3395 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -845,13 +845,7 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov } function viewImagePath( $path, $querySep='&' ) { - if ( strncmp( $path, ZM_DIR_IMAGES, strlen(ZM_DIR_IMAGES) ) == 0 ) { - // Thumbnails - return( $path ); - } elseif ( strpos( ZM_DIR_EVENTS, '/' ) === 0 ) { - return( '?view=image'.$querySep.'path='.$path ); - } - return( ZM_DIR_EVENTS.'/'.$path ); + return( '?view=image'.$querySep.'path='.$path ); } function createListThumbnail( $event, $overwrite=false ) { From a0299099729199439a0bb8f7e7e38061b04b0244 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 28 Dec 2018 09:46:13 -0600 Subject: [PATCH 232/240] fix path to thumb and anal images (#2367) --- web/includes/Event.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/web/includes/Event.php b/web/includes/Event.php index 27d9ae015..a4f389aca 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -414,15 +414,13 @@ class Event { if ( ! file_exists($captPath) ) { Error( "Capture file does not exist at $captPath" ); } - $thumbCaptPath = ZM_DIR_IMAGES.'/'.$this->{'Id'}.'-'.$captImage; - //echo "CI:$captImage, CP:$captPath, TCP:$thumbCaptPath
          "; + //echo "CI:$captImage, CP:$captPath, TCP:$captPath
          "; $analImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $frame['FrameId'] ); $analPath = $eventPath.'/'.$analImage; - $thumbAnalPath = ZM_DIR_IMAGES.'/'.$this->{'Id'}.'-'.$analImage; - //echo "AI:$analImage, AP:$analPath, TAP:$thumbAnalPath
          "; + //echo "AI:$analImage, AP:$analPath, TAP:$analPath
          "; $alarmFrame = $frame['Type']=='Alarm'; @@ -440,8 +438,8 @@ class Event { $fraction = sprintf( '%.3f', $scale/SCALE_BASE ); $scale = (int)round( $scale ); - $thumbCaptPath = preg_replace( '/\.jpg$/', "-$scale.jpg", $thumbCaptPath ); - $thumbAnalPath = preg_replace( '/\.jpg$/', "-$scale.jpg", $thumbAnalPath ); + $thumbCaptPath = preg_replace( '/\.jpg$/', "-$scale.jpg", $captPath ); + $thumbAnalPath = preg_replace( '/\.jpg$/', "-$scale.jpg", $analPath ); if ( $isAnalImage ) { $imagePath = $analPath; From 893048c306c68e15df4d3ed9f167c48eb6d94ac6 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 28 Dec 2018 09:46:27 -0600 Subject: [PATCH 233/240] remove option to build with no ffmpeg (#2365) --- CMakeLists.txt | 252 ++++++++++++++++++++++++------------------------- INSTALL | 1 - 2 files changed, 123 insertions(+), 130 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0d037099..602549ab9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,8 +186,6 @@ set(ZM_MYSQL_ENGINE "InnoDB" CACHE STRING set(ZM_NO_MMAP "OFF" CACHE BOOL "Set to ON to not use mmap shared memory. Shouldn't be enabled unless you experience problems with the shared memory. default: OFF") -set(ZM_NO_FFMPEG "OFF" CACHE BOOL - "Set to ON to skip ffmpeg checks and force building ZM without ffmpeg. default: OFF") set(ZM_NO_LIBVLC "OFF" CACHE BOOL "Set to ON to skip libvlc checks and force building ZM without libvlc. default: OFF") set(ZM_NO_CURL "OFF" CACHE BOOL @@ -518,141 +516,137 @@ endif(MP4V2_LIBRARIES) set(PATH_FFMPEG "") set(OPT_FFMPEG "no") -# Do not check for ffmpeg if ZM_NO_FFMPEG is on -if(NOT ZM_NO_FFMPEG) - # avformat (using find_library and find_path) - find_library(AVFORMAT_LIBRARIES avformat) - if(AVFORMAT_LIBRARIES) - set(HAVE_LIBAVFORMAT 1) - list(APPEND ZM_BIN_LIBS "${AVFORMAT_LIBRARIES}") - find_path(AVFORMAT_INCLUDE_DIR "libavformat/avformat.h" /usr/include/ffmpeg) - if(AVFORMAT_INCLUDE_DIR) - include_directories("${AVFORMAT_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${AVFORMAT_INCLUDE_DIR}") - endif(AVFORMAT_INCLUDE_DIR) - mark_as_advanced(FORCE AVFORMAT_LIBRARIES AVFORMAT_INCLUDE_DIR) - check_include_file("libavformat/avformat.h" HAVE_LIBAVFORMAT_AVFORMAT_H) - set(optlibsfound "${optlibsfound} AVFormat") - else(AVFORMAT_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} AVFormat") - endif(AVFORMAT_LIBRARIES) +# avformat (using find_library and find_path) +find_library(AVFORMAT_LIBRARIES avformat) +if(AVFORMAT_LIBRARIES) + set(HAVE_LIBAVFORMAT 1) + list(APPEND ZM_BIN_LIBS "${AVFORMAT_LIBRARIES}") + find_path(AVFORMAT_INCLUDE_DIR "libavformat/avformat.h" /usr/include/ffmpeg) + if(AVFORMAT_INCLUDE_DIR) + include_directories("${AVFORMAT_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${AVFORMAT_INCLUDE_DIR}") + endif(AVFORMAT_INCLUDE_DIR) + mark_as_advanced(FORCE AVFORMAT_LIBRARIES AVFORMAT_INCLUDE_DIR) + check_include_file("libavformat/avformat.h" HAVE_LIBAVFORMAT_AVFORMAT_H) + set(optlibsfound "${optlibsfound} AVFormat") +else(AVFORMAT_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} AVFormat") +endif(AVFORMAT_LIBRARIES) - # avcodec (using find_library and find_path) - find_library(AVCODEC_LIBRARIES avcodec) - if(AVCODEC_LIBRARIES) - set(HAVE_LIBAVCODEC 1) - list(APPEND ZM_BIN_LIBS "${AVCODEC_LIBRARIES}") - find_path(AVCODEC_INCLUDE_DIR "libavcodec/avcodec.h" /usr/include/ffmpeg) - if(AVCODEC_INCLUDE_DIR) - include_directories("${AVCODEC_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${AVCODEC_INCLUDE_DIR}") - endif(AVCODEC_INCLUDE_DIR) - mark_as_advanced(FORCE AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIR) - check_include_file("libavcodec/avcodec.h" HAVE_LIBAVCODEC_AVCODEC_H) - set(optlibsfound "${optlibsfound} AVCodec") - else(AVCODEC_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} AVCodec") - endif(AVCODEC_LIBRARIES) +# avcodec (using find_library and find_path) +find_library(AVCODEC_LIBRARIES avcodec) +if(AVCODEC_LIBRARIES) + set(HAVE_LIBAVCODEC 1) + list(APPEND ZM_BIN_LIBS "${AVCODEC_LIBRARIES}") + find_path(AVCODEC_INCLUDE_DIR "libavcodec/avcodec.h" /usr/include/ffmpeg) + if(AVCODEC_INCLUDE_DIR) + include_directories("${AVCODEC_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${AVCODEC_INCLUDE_DIR}") + endif(AVCODEC_INCLUDE_DIR) + mark_as_advanced(FORCE AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIR) + check_include_file("libavcodec/avcodec.h" HAVE_LIBAVCODEC_AVCODEC_H) + set(optlibsfound "${optlibsfound} AVCodec") +else(AVCODEC_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} AVCodec") +endif(AVCODEC_LIBRARIES) - # avdevice (using find_library and find_path) - find_library(AVDEVICE_LIBRARIES avdevice) - if(AVDEVICE_LIBRARIES) - set(HAVE_LIBAVDEVICE 1) - list(APPEND ZM_BIN_LIBS "${AVDEVICE_LIBRARIES}") - find_path(AVDEVICE_INCLUDE_DIR "libavdevice/avdevice.h" /usr/include/ffmpeg) - if(AVDEVICE_INCLUDE_DIR) - include_directories("${AVDEVICE_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${AVDEVICE_INCLUDE_DIR}") - endif(AVDEVICE_INCLUDE_DIR) - mark_as_advanced(FORCE AVDEVICE_LIBRARIES AVDEVICE_INCLUDE_DIR) - check_include_file("libavdevice/avdevice.h" HAVE_LIBAVDEVICE_AVDEVICE_H) - set(optlibsfound "${optlibsfound} AVDevice") - else(AVDEVICE_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} AVDevice") - endif(AVDEVICE_LIBRARIES) +# avdevice (using find_library and find_path) +find_library(AVDEVICE_LIBRARIES avdevice) +if(AVDEVICE_LIBRARIES) + set(HAVE_LIBAVDEVICE 1) + list(APPEND ZM_BIN_LIBS "${AVDEVICE_LIBRARIES}") + find_path(AVDEVICE_INCLUDE_DIR "libavdevice/avdevice.h" /usr/include/ffmpeg) + if(AVDEVICE_INCLUDE_DIR) + include_directories("${AVDEVICE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${AVDEVICE_INCLUDE_DIR}") + endif(AVDEVICE_INCLUDE_DIR) + mark_as_advanced(FORCE AVDEVICE_LIBRARIES AVDEVICE_INCLUDE_DIR) + check_include_file("libavdevice/avdevice.h" HAVE_LIBAVDEVICE_AVDEVICE_H) + set(optlibsfound "${optlibsfound} AVDevice") +else(AVDEVICE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} AVDevice") +endif(AVDEVICE_LIBRARIES) - # avutil (using find_library and find_path) - find_library(AVUTIL_LIBRARIES avutil) - if(AVUTIL_LIBRARIES) - set(HAVE_LIBAVUTIL 1) - list(APPEND ZM_BIN_LIBS "${AVUTIL_LIBRARIES}") - find_path(AVUTIL_INCLUDE_DIR "libavutil/avutil.h" /usr/include/ffmpeg) - if(AVUTIL_INCLUDE_DIR) - include_directories("${AVUTIL_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${AVUTIL_INCLUDE_DIR}") - endif(AVUTIL_INCLUDE_DIR) - mark_as_advanced(FORCE AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIR) - check_include_file("libavutil/avutil.h" HAVE_LIBAVUTIL_AVUTIL_H) - check_include_file("libavutil/mathematics.h" HAVE_LIBAVUTIL_MATHEMATICS_H) - check_include_file("libavutil/hwcontext.h" HAVE_LIBAVUTIL_HWCONTEXT_H) - set(optlibsfound "${optlibsfound} AVUtil") - else(AVUTIL_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} AVUtil") - endif(AVUTIL_LIBRARIES) +# avutil (using find_library and find_path) +find_library(AVUTIL_LIBRARIES avutil) +if(AVUTIL_LIBRARIES) + set(HAVE_LIBAVUTIL 1) + list(APPEND ZM_BIN_LIBS "${AVUTIL_LIBRARIES}") + find_path(AVUTIL_INCLUDE_DIR "libavutil/avutil.h" /usr/include/ffmpeg) + if(AVUTIL_INCLUDE_DIR) + include_directories("${AVUTIL_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${AVUTIL_INCLUDE_DIR}") + endif(AVUTIL_INCLUDE_DIR) + mark_as_advanced(FORCE AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIR) + check_include_file("libavutil/avutil.h" HAVE_LIBAVUTIL_AVUTIL_H) + check_include_file("libavutil/mathematics.h" HAVE_LIBAVUTIL_MATHEMATICS_H) + check_include_file("libavutil/hwcontext.h" HAVE_LIBAVUTIL_HWCONTEXT_H) + set(optlibsfound "${optlibsfound} AVUtil") +else(AVUTIL_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} AVUtil") +endif(AVUTIL_LIBRARIES) - # swscale (using find_library and find_path) - find_library(SWSCALE_LIBRARIES swscale) - if(SWSCALE_LIBRARIES) - set(HAVE_LIBSWSCALE 1) - list(APPEND ZM_BIN_LIBS "${SWSCALE_LIBRARIES}") - find_path(SWSCALE_INCLUDE_DIR "libswscale/swscale.h" /usr/include/ffmpeg) - if(SWSCALE_INCLUDE_DIR) - include_directories("${SWSCALE_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${SWSCALE_INCLUDE_DIR}") - endif(SWSCALE_INCLUDE_DIR) - mark_as_advanced(FORCE SWSCALE_LIBRARIES SWSCALE_INCLUDE_DIR) - check_include_file("libswscale/swscale.h" HAVE_LIBSWSCALE_SWSCALE_H) - set(optlibsfound "${optlibsfound} SWScale") - else(SWSCALE_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} SWScale") - endif(SWSCALE_LIBRARIES) +# swscale (using find_library and find_path) +find_library(SWSCALE_LIBRARIES swscale) +if(SWSCALE_LIBRARIES) + set(HAVE_LIBSWSCALE 1) + list(APPEND ZM_BIN_LIBS "${SWSCALE_LIBRARIES}") + find_path(SWSCALE_INCLUDE_DIR "libswscale/swscale.h" /usr/include/ffmpeg) + if(SWSCALE_INCLUDE_DIR) + include_directories("${SWSCALE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${SWSCALE_INCLUDE_DIR}") + endif(SWSCALE_INCLUDE_DIR) + mark_as_advanced(FORCE SWSCALE_LIBRARIES SWSCALE_INCLUDE_DIR) + check_include_file("libswscale/swscale.h" HAVE_LIBSWSCALE_SWSCALE_H) + set(optlibsfound "${optlibsfound} SWScale") +else(SWSCALE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} SWScale") +endif(SWSCALE_LIBRARIES) - # SWresample (using find_library and find_path) - find_library(SWRESAMPLE_LIBRARIES swresample) - if(SWRESAMPLE_LIBRARIES) - set(HAVE_LIBSWRESAMPLE 1) - list(APPEND ZM_BIN_LIBS "${SWRESAMPLE_LIBRARIES}") - find_path(SWRESAMPLE_INCLUDE_DIR "libswresample/swresample.h" /usr/include/ffmpeg) - if(SWRESAMPLE_INCLUDE_DIR) - include_directories("${SWRESAMPLE_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${SWRESAMPLE_INCLUDE_DIR}") - endif(SWRESAMPLE_INCLUDE_DIR) - mark_as_advanced(FORCE SWRESAMPLE_LIBRARIES SWRESAMPLE_INCLUDE_DIR) - check_include_file("libswresample/swresample.h" HAVE_LIBSWRESAMPLE_SWRESAMPLE_H) - set(optlibsfound "${optlibsfound} SWResample") - else(SWRESAMPLE_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} SWResample") +# SWresample (using find_library and find_path) +find_library(SWRESAMPLE_LIBRARIES swresample) +if(SWRESAMPLE_LIBRARIES) + set(HAVE_LIBSWRESAMPLE 1) + list(APPEND ZM_BIN_LIBS "${SWRESAMPLE_LIBRARIES}") + find_path(SWRESAMPLE_INCLUDE_DIR "libswresample/swresample.h" /usr/include/ffmpeg) + if(SWRESAMPLE_INCLUDE_DIR) + include_directories("${SWRESAMPLE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${SWRESAMPLE_INCLUDE_DIR}") + endif(SWRESAMPLE_INCLUDE_DIR) + mark_as_advanced(FORCE SWRESAMPLE_LIBRARIES SWRESAMPLE_INCLUDE_DIR) + check_include_file("libswresample/swresample.h" HAVE_LIBSWRESAMPLE_SWRESAMPLE_H) + set(optlibsfound "${optlibsfound} SWResample") +else(SWRESAMPLE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} SWResample") - # AVresample (using find_library and find_path) - find_library(AVRESAMPLE_LIBRARIES avresample) - if(AVRESAMPLE_LIBRARIES) - set(HAVE_LIBAVRESAMPLE 1) - list(APPEND ZM_BIN_LIBS "${AVRESAMPLE_LIBRARIES}") - find_path(AVRESAMPLE_INCLUDE_DIR "libavresample/avresample.h" /usr/include/ffmpeg) - if(AVRESAMPLE_INCLUDE_DIR) - include_directories("${AVRESAMPLE_INCLUDE_DIR}") - set(CMAKE_REQUIRED_INCLUDES "${AVRESAMPLE_INCLUDE_DIR}") - endif(AVRESAMPLE_INCLUDE_DIR) - mark_as_advanced(FORCE AVRESAMPLE_LIBRARIES AVRESAMPLE_INCLUDE_DIR) - check_include_file("libavresample/avresample.h" HAVE_LIBAVRESAMPLE_AVRESAMPLE_H) - set(optlibsfound "${optlibsfound} AVResample") - else(AVRESAMPLE_LIBRARIES) - set(optlibsnotfound "${optlibsnotfound} AVResample") - endif(AVRESAMPLE_LIBRARIES) + # AVresample (using find_library and find_path) + find_library(AVRESAMPLE_LIBRARIES avresample) + if(AVRESAMPLE_LIBRARIES) + set(HAVE_LIBAVRESAMPLE 1) + list(APPEND ZM_BIN_LIBS "${AVRESAMPLE_LIBRARIES}") + find_path(AVRESAMPLE_INCLUDE_DIR "libavresample/avresample.h" /usr/include/ffmpeg) + if(AVRESAMPLE_INCLUDE_DIR) + include_directories("${AVRESAMPLE_INCLUDE_DIR}") + set(CMAKE_REQUIRED_INCLUDES "${AVRESAMPLE_INCLUDE_DIR}") + endif(AVRESAMPLE_INCLUDE_DIR) + mark_as_advanced(FORCE AVRESAMPLE_LIBRARIES AVRESAMPLE_INCLUDE_DIR) + check_include_file("libavresample/avresample.h" HAVE_LIBAVRESAMPLE_AVRESAMPLE_H) + set(optlibsfound "${optlibsfound} AVResample") + else(AVRESAMPLE_LIBRARIES) + set(optlibsnotfound "${optlibsnotfound} AVResample") + endif(AVRESAMPLE_LIBRARIES) - endif(SWRESAMPLE_LIBRARIES) +endif(SWRESAMPLE_LIBRARIES) - # Find the path to the ffmpeg executable - find_program(FFMPEG_EXECUTABLE - NAMES ffmpeg avconv - PATH_SUFFIXES ffmpeg) - if(FFMPEG_EXECUTABLE) - set(PATH_FFMPEG "${FFMPEG_EXECUTABLE}") - set(OPT_FFMPEG "yes") - mark_as_advanced(FFMPEG_EXECUTABLE) - endif(FFMPEG_EXECUTABLE) - -endif(NOT ZM_NO_FFMPEG) +# Find the path to the ffmpeg executable +find_program(FFMPEG_EXECUTABLE + NAMES ffmpeg avconv + PATH_SUFFIXES ffmpeg) +if(FFMPEG_EXECUTABLE) + set(PATH_FFMPEG "${FFMPEG_EXECUTABLE}") + set(OPT_FFMPEG "yes") + mark_as_advanced(FFMPEG_EXECUTABLE) +endif(FFMPEG_EXECUTABLE) # Do not check for libvlc if ZM_NO_LIBVLC is on if(NOT ZM_NO_LIBVLC) diff --git a/INSTALL b/INSTALL index 666105c40..a837a516a 100644 --- a/INSTALL +++ b/INSTALL @@ -62,7 +62,6 @@ Advanced: ZM_EXTRA_LIBS A list of optional libraries, separated by semicolons, e.g. ssl;theora ZM_MYSQL_ENGINE MySQL engine to use with database, default: InnoDB ZM_NO_MMAP Set to ON to not use mmap shared memory. Shouldn't be enabled unless you experience problems with the shared memory. default: OFF - ZM_NO_FFMPEG Set to ON to skip ffmpeg checks and force building ZM without ffmpeg. default: OFF ZM_NO_X10 Set to ON to build ZoneMinder without X10 support. default: OFF ZM_PERL_MM_PARMS By default, ZoneMinder's Perl modules are installed into the Vendor folders, as defined by your installation of Perl. You can change that here. Consult Perl's MakeMaker documentation for a definition of acceptable parameters. If you set this to something that causes the modules to be installed outside Perl's normal serach path, then you will also need to set ZM_PERL_SEARCH_PATH accordingly. default: "INSTALLDIRS=vendor NO_PACKLIST=1 NO_PERLLOCAL=1" ZM_PERL_SEARCH_PATH Use to add a folder to your Perl's search path. This will need to be set in cases where ZM_PERL_MM_PARMS has been modified such that ZoneMinder's Perl modules are installed outside Perl's default search path. default: "" From b8335b3e2af6b3819ecad16096ca2a47a352629d Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 28 Dec 2018 09:49:05 -0600 Subject: [PATCH 234/240] Update definezone.rst --- docs/userguide/definezone.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/userguide/definezone.rst b/docs/userguide/definezone.rst index cf33f44c9..98c869e6c 100644 --- a/docs/userguide/definezone.rst +++ b/docs/userguide/definezone.rst @@ -104,6 +104,9 @@ Overload Frame Ignore Count * Number of Blobs > Max Blobs The idea is that after a change like a light going on that is considered too big to count as an alarm, it could take a couple of frames for things to settle down again. +Extend Alarm Frame Count + This field applies to Preclusive Zones only. Placing a value in this field holds the Preclusive zone active for the specified number of frames after the initial triggering event. This is useful in cases where a sudden change in light level triggers the Preclusive zone, but the zone needs to be held active for a few frames as the camera itself adjusts to that change in light level. + Other information ----------------- Refer to `this `__ user contributed Zone guide for additional information will illustrations if you are new to zones and need more help. From 77f51e6d6a8b5116c9feb511dd3a05a9f8f322c6 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 28 Dec 2018 12:34:09 -0600 Subject: [PATCH 235/240] attempt to trigger readthedocs --- temp | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 temp diff --git a/temp b/temp new file mode 100644 index 000000000..e69de29bb From 0d1539802ca489af306398c1cecbc16137a44f26 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 28 Dec 2018 12:34:37 -0600 Subject: [PATCH 236/240] attempt to trigger readthedocs --- temp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 temp diff --git a/temp b/temp deleted file mode 100644 index e69de29bb..000000000 From 35f89962e277b53b738c637bacddfa8f091740e3 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 28 Dec 2018 12:40:17 -0600 Subject: [PATCH 237/240] mention exclude alarm frame feature in preclusive --- docs/userguide/definezone.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/definezone.rst b/docs/userguide/definezone.rst index 98c869e6c..97f42f864 100644 --- a/docs/userguide/definezone.rst +++ b/docs/userguide/definezone.rst @@ -29,7 +29,7 @@ Type Triggers an alarm when motion is detected within it, as long as no alarms have already been triggered in an Active zone. This is the most specialized of the zone types. For instance in the camera covering my garden I keep watch for a hedgehog that visits most nights and scoffs the food out of my cats bowls. By creating a sensitive Exclusive zone in that area I can ensure that a hedgehog alarm will only trigger if there is activity in that small area. If something much bigger occurs, like someone walking by it will trigger a regular alarm and not one from the Exclusive zone. Thus I can ensure I get alarms for big events and also special small events but not the noise in between. * Preclusive - This zone type is relatively recent. It is called a Preclusive zone because if it is triggered it actually precludes an alarm being generated for that image frame. So motion or other changes that occur in a Preclusive zone will have the effect of ensuring that no alarm occurs at all. The application for this zone type is primarily as a shortcut for detecting general large-scale lighting or other changes. Generally this may be achieved by limiting the maximum number of alarm pixels or other measure in an Active zone. However in some cases that zone may cover an area where the area of variable illumination occurs in different places as the sun and/or shadows move and it thus may be difficult to come up with general values. Additionally, if the sun comes out rapidly then although the initial change may be ignored in this way as the reference image catches up an alarm may ultimately be triggered as the image becomes less different. Using one or more Preclusive zones offers a different approach. Preclusive zones are designed to be fairly small, even just a few pixels across, with quite low alarm thresholds. They should be situated in areas of the image that are less likely to have motion occur such as high on a wall or in a corner. Should a general illumination change occur they would be triggered at least as early as any Active zones and prevent any other zones from generating an alarm. Obviously careful placement is required to ensure that they do not cancel any genuine alarms or that they are not so close together that any motion just hops from one Preclusive zone to another. Preclusive zones may also be used to reduce processing time by situating one over an Active zone. The Preclusive zone is processed first; if it is small, and is triggered, the rest of the zone/image will not be processed. + This zone type is relatively recent. It is called a Preclusive zone because if it is triggered it actually precludes an alarm being generated for that image frame. So motion or other changes that occur in a Preclusive zone will have the effect of ensuring that no alarm occurs at all. The application for this zone type is primarily as a shortcut for detecting general large-scale lighting or other changes. Generally this may be achieved by limiting the maximum number of alarm pixels or other measure in an Active zone. However in some cases that zone may cover an area where the area of variable illumination occurs in different places as the sun and/or shadows move and it thus may be difficult to come up with general values. Additionally, if the sun comes out rapidly then although the initial change may be ignored in this way as the reference image catches up an alarm may ultimately be triggered as the image becomes less different. Using one or more Preclusive zones offers a different approach. Preclusive zones are designed to be fairly small, even just a few pixels across, with quite low alarm thresholds. They should be situated in areas of the image that are less likely to have motion occur such as high on a wall or in a corner. Should a general illumination change occur they would be triggered at least as early as any Active zones and prevent any other zones from generating an alarm. Obviously careful placement is required to ensure that they do not cancel any genuine alarms or that they are not so close together that any motion just hops from one Preclusive zone to another. Preclusive zones may also be used to reduce processing time by situating one over an Active zone. The Preclusive zone is processed first; if it is small, and is triggered, the rest of the zone/image will not be processed. See Extend Alarm Frame Count below for a way to hold the preclusive zone active for an extended period. * Inactive Suppresses the detection of motion within it. This can be layered on top of any other zone type, preventing motion within the Inactive zone from being effective for any other zone type. Use inactive zones to cover areas in which nothing notable will ever happen or where you get false alarms that don't relate to what you are trying to monitor. Inactive zones may be overlaid on other zones to blank out areas, and are processed first (with the exception of Privacy zones, see below). As a general practice, you should try and make zones abut each other instead of overlapping to avoid repeated duplicate processing of the same area. From 3258d8e590673752a2dbc773d0847834ca8640b4 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 29 Dec 2018 08:52:58 -0600 Subject: [PATCH 238/240] remove ZM_DIR_IMAGES (#2374) --- CMakeLists.txt | 4 --- INSTALL | 5 ++- conf.d/01-system-paths.conf.in | 5 --- distros/debian/rules | 1 - distros/redhat/CMakeLists.txt | 4 +-- .../redhat/httpd/zoneminder.httpd.tmpfiles.in | 1 - .../redhat/nginx/zoneminder.nginx.tmpfiles.in | 1 - distros/redhat/zoneminder.spec | 2 -- distros/ubuntu1204/rules | 1 - distros/ubuntu1504_cmake_split_packages/rules | 1 - distros/ubuntu1604/rules | 1 - docs/installationguide/dedicateddrive.rst | 1 - docs/userguide/options/options_paths.rst | 2 -- scripts/zmaudit.pl.in | 4 +-- src/zm_config.cpp | 2 -- src/zm_config.h.in | 1 - web/ajax/zone.php | 31 ------------------- .../Controller/Component/ImageComponent.php | 6 ++-- web/api/app/Controller/EventsController.php | 1 - web/api/app/Controller/ZonesController.php | 29 ----------------- web/index.php | 4 +-- web/lang/ro_ro.php | 4 --- 22 files changed, 10 insertions(+), 101 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 602549ab9..9646ffc3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,9 +162,6 @@ set(ZM_WEB_GROUP "" CACHE STRING Leave empty to be the same as the web user") set(ZM_DIR_EVENTS "${ZM_CONTENTDIR}/events" CACHE PATH "Location where events are recorded to, default: ZM_CONTENTDIR/events") -set(ZM_DIR_IMAGES "${ZM_CONTENTDIR}/images" CACHE PATH - "Location where images, not directly associated with events, - are recorded to, default: ZM_CONTENTDIR/images") set(ZM_DIR_SOUNDS "sounds" CACHE PATH "Location to look for optional sound files, default: sounds") set(ZM_PATH_ZMS "/cgi-bin/nph-zms" CACHE PATH @@ -225,7 +222,6 @@ if((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc")) set(ZM_WEBDIR "/usr/share/zoneminder/www") set(ZM_CGIDIR "/usr/libexec/zoneminder/cgi-bin") set(ZM_DIR_EVENTS "/var/lib/zoneminder/events") - set(ZM_DIR_IMAGES "/var/lib/zoneminder/images") set(ZM_PATH_ZMS "/cgi-bin-zm/nph-zms") elseif(ZM_TARGET_DISTRO STREQUAL "OS13") set(ZM_RUNDIR "/var/run/zoneminder") diff --git a/INSTALL b/INSTALL index a837a516a..ecf7b909a 100644 --- a/INSTALL +++ b/INSTALL @@ -51,7 +51,6 @@ Possible configuration options: ZM_WEB_USER The user apache or the local web server runs on. Leave empty for automatic detection. If that fails, you can use this variable to force ZM_WEB_GROUP The group apache or the local web server runs on, Leave empty to be the same as the web user ZM_DIR_EVENTS Location where events are recorded to, default: ZM_CONTENTDIR/events - ZM_DIR_IMAGES Location where images, not directly associated with events, are recorded to, default: ZM_CONTENTDIR/images ZM_DIR_SOUNDS Location to look for optional sound files, default: sounds ZM_PATH_ZMS Web url to zms streaming server, default: /cgi-bin/nph-zms Advanced: @@ -129,8 +128,8 @@ cmake -C zm_conf.cmake [extra options] . 2) Run "make" to compile ZoneMinder 3) Run "make install" (as root, or use sudo) to install ZoneMinder to your system. -4) Depending on your configuration: If the DIR_EVENTS and DIR_IMAGES options are set to default (pointing to web directory/events and web directory/images), You will need to update the symlinks in the web directory to the correct folders. e.g. web directory/events should point to the real events directory, and likewise for the images directory. -You can use the zmlinkcontent.sh script for this. For example, if /var/lib/zoneminder is the folder that contains the "images" and "events" directories, you can use: +4) Depending on your configuration: If DIR_EVENTS is set to default, You will need to update the symlinks in the web directory to the correct folders. e.g. web directory/events should point to the real events directory. +You can use the zmlinkcontent.sh script for this. For example, if /var/lib/zoneminder is the folder that contains the "events" directory, you can use: ./zmlinkcontent.sh /var/lib/zoneminder By default, the content directory for new installations is /var/lib/zoneminder. This can be overridden in cmake with the ZM_CONTENTDIR option. e.g. cmake -DZM_CONTENTDIR="/some/big/storage/zm" . diff --git a/conf.d/01-system-paths.conf.in b/conf.d/01-system-paths.conf.in index e97433ba2..e1aaf0bef 100644 --- a/conf.d/01-system-paths.conf.in +++ b/conf.d/01-system-paths.conf.in @@ -16,11 +16,6 @@ # The web account user must have full read/write permission to this folder. ZM_DIR_EVENTS=@ZM_DIR_EVENTS@ -# Full path to the folder images, not directly associated with events, -# are recorded to. -# The web account user must have full read/write permission to this folder. -ZM_DIR_IMAGES=@ZM_DIR_IMAGES@ - # Foldername under the webroot where ZoneMinder looks for optional sound files # to play when an alarm is detected. ZM_DIR_SOUNDS=@ZM_DIR_SOUNDS@ diff --git a/distros/debian/rules b/distros/debian/rules index fe725c2d0..6185838e0 100755 --- a/distros/debian/rules +++ b/distros/debian/rules @@ -24,7 +24,6 @@ override_dh_auto_configure: -DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \ -DZM_CONFIG_DIR="/etc/zm" \ -DZM_DIR_EVENTS="/var/cache/zoneminder/events" \ - -DZM_DIR_IMAGES="/var/cache/zoneminder/images" \ -DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" override_dh_auto_install: diff --git a/distros/redhat/CMakeLists.txt b/distros/redhat/CMakeLists.txt index 06b0e8cbf..f1a1bc75b 100644 --- a/distros/redhat/CMakeLists.txt +++ b/distros/redhat/CMakeLists.txt @@ -21,7 +21,7 @@ endif(ZM_TARGET_DISTRO MATCHES "^el") # Configure the common zoneminder files configure_file(common/zoneminder.logrotate.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.logrotate @ONLY) configure_file(common/zoneminder.service.in ${CMAKE_CURRENT_SOURCE_DIR}/zoneminder.service @ONLY) -file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events images temp) +file(MAKE_DIRECTORY sock swap zoneminder zoneminder-upload events temp) # Configure the Apache zoneminder files configure_file(httpd/zm-httpd.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/zm-httpd.conf @ONLY) @@ -52,7 +52,7 @@ install(DIRECTORY zoneminder DESTINATION /var/log DIRECTORY_PERMISSIONS OWNER_WR install(DIRECTORY zoneminder DESTINATION /var/run DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY zoneminder DESTINATION /var/cache DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(DIRECTORY zoneminder-upload DESTINATION /var/spool DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) -install(DIRECTORY events images temp DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +install(DIRECTORY events temp DESTINATION /var/lib/zoneminder DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # Install the Apache zoneminder files install(FILES zm-httpd.conf DESTINATION /usr/lib/systemd/system/zoneminder.service.d PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/distros/redhat/httpd/zoneminder.httpd.tmpfiles.in b/distros/redhat/httpd/zoneminder.httpd.tmpfiles.in index f24babdc6..b403fb24d 100644 --- a/distros/redhat/httpd/zoneminder.httpd.tmpfiles.in +++ b/distros/redhat/httpd/zoneminder.httpd.tmpfiles.in @@ -2,5 +2,4 @@ D @ZM_TMPDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_SOCKDIR@ 0755 @WEB_USER@ @WEB_GROUP@ D @ZM_CACHEDIR@ 0755 @WEB_USER@ @WEB_GROUP@ d @ZM_DIR_EVENTS@ 0755 @WEB_USER@ @WEB_GROUP@ -D @ZM_DIR_IMAGES@ 0755 @WEB_USER@ @WEB_GROUP@ diff --git a/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in b/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in index 1c581fcb9..502b817d8 100644 --- a/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in +++ b/distros/redhat/nginx/zoneminder.nginx.tmpfiles.in @@ -2,5 +2,4 @@ D @ZM_TMPDIR@ 0755 nginx nginx D @ZM_SOCKDIR@ 0755 nginx nginx D @ZM_CACHEDIR@ 0755 nginx nginx d @ZM_DIR_EVENTS@ 0755 nginx nginx -D @ZM_DIR_IMAGES@ 0755 nginx nginx diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index cbda079ca..8f30d6fee 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -377,7 +377,6 @@ EOF %{_tmpfilesdir}/zoneminder.httpd.tmpfiles.conf %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/events -%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/images %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/sock %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/swap %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/temp @@ -402,7 +401,6 @@ EOF %{_tmpfilesdir}/zoneminder.nginx.tmpfiles.conf %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/events -%dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/images %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/sock %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/swap %dir %attr(755,nginx,nginx) %{_sharedstatedir}/zoneminder/temp diff --git a/distros/ubuntu1204/rules b/distros/ubuntu1204/rules index f971e9cc3..20dd303f8 100755 --- a/distros/ubuntu1204/rules +++ b/distros/ubuntu1204/rules @@ -27,7 +27,6 @@ override_dh_auto_configure: -DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \ -DZM_CACHEDIR="/var/cache/zoneminder/cache" \ -DZM_DIR_EVENTS="/var/cache/zoneminder/events" \ - -DZM_DIR_IMAGES="/var/cache/zoneminder/images" \ -DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" override_dh_clean: diff --git a/distros/ubuntu1504_cmake_split_packages/rules b/distros/ubuntu1504_cmake_split_packages/rules index 0eca4b511..f6169c495 100755 --- a/distros/ubuntu1504_cmake_split_packages/rules +++ b/distros/ubuntu1504_cmake_split_packages/rules @@ -64,7 +64,6 @@ override_dh_auto_configure: -DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \ -DZM_CONFIG_DIR="/etc/zm" \ -DZM_DIR_EVENTS="/var/cache/zoneminder/events" \ - -DZM_DIR_IMAGES="/var/cache/zoneminder/images" \ -DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" override_dh_auto_test: diff --git a/distros/ubuntu1604/rules b/distros/ubuntu1604/rules index f0808a8e1..98b9ac0a2 100755 --- a/distros/ubuntu1604/rules +++ b/distros/ubuntu1604/rules @@ -27,7 +27,6 @@ override_dh_auto_configure: -DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \ -DZM_CACHEDIR="/var/cache/zoneminder/cache" \ -DZM_DIR_EVENTS="/var/cache/zoneminder/events" \ - -DZM_DIR_IMAGES="/var/cache/zoneminder/images" \ -DZM_PATH_ZMS="/zm/cgi-bin/nph-zms" override_dh_clean: diff --git a/docs/installationguide/dedicateddrive.rst b/docs/installationguide/dedicateddrive.rst index f0dfadc28..6a7367b8b 100644 --- a/docs/installationguide/dedicateddrive.rst +++ b/docs/installationguide/dedicateddrive.rst @@ -31,7 +31,6 @@ Add the following content to the file and save your changes: :: ZM_DIR_EVENTS=/full/path/to/the/events/folder - ZM_DIR_IMAGES=/full/path/to/the/images/folder **Step 5:** Start ZoneMinder and inspect the ZoneMinder log files for errors. :: diff --git a/docs/userguide/options/options_paths.rst b/docs/userguide/options/options_paths.rst index 024998194..1d4911f70 100644 --- a/docs/userguide/options/options_paths.rst +++ b/docs/userguide/options/options_paths.rst @@ -7,8 +7,6 @@ ZM_DIR_EVENTS - This is the path to the events directory where all the event ima USE_DEEP_STORAGE - Traditionally ZoneMinder stores all events for a monitor in one directory for that monitor. This is simple and efficient except when you have very large amounts of events. Some filesystems are unable to store more than 32k files in one directory and even without this limitation, large numbers of files in a directory can slow creation and deletion of files. This option allows you to select an alternate method of storing events by year/month/day/hour/min/second which has the effect of separating events out into more directories, resulting in less per directory, and also making it easier to manually navigate to any events that may have happened at a particular time or date. -DIR_IMAGES - ZoneMinder generates a myriad of images, mostly of which are associated with events. For those that aren't this is where they go. CAUTION: The directory you specify here cannot be outside the web root. This is a common mistake. Most users should never change this value. If you intend to save images to a second disk or network share, then you should mount the drive or share directly to the ZoneMinder images folder or follow the instructions in the ZoneMinder Wiki titled Using a dedicated Hard Drive. - DIR_SOUNDS - ZoneMinder can optionally play a sound file when an alarm is detected. This indicates where to look for this file. CAUTION: The directory you specify here cannot be outside the web root. Most users should never change this value. PATH_ZMS - The ZoneMinder streaming server is required to send streamed images to your browser. It will be installed into the cgi-bin path given at configuration time. This option determines what the web path to the server is rather than the local path on your machine. Ordinarily the streaming server runs in parser-header mode however if you experience problems with streaming you can change this to non-parsed-header (nph) mode by changing 'zms' to 'nph-zms'. diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index fdb9d68ff..10917a729 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -48,7 +48,6 @@ use Time::HiRes qw/gettimeofday/; use Getopt::Long; use autouse 'Pod::Usage'=>qw(pod2usage); -use constant IMAGE_PATH => $Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_IMAGES}; use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|) ? $Config{ZM_DIR_EVENTS} : ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS}) @@ -144,7 +143,8 @@ require ZoneMinder::Event; my $max_image_age = 6/24; # 6 hours my $max_swap_age = 24/24; # 24 hours -my $image_path = IMAGE_PATH; +# images now live under the event path +my $image_path = EVENT_PATH; my $loop = 1; my $cleaned = 0; diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 6d63be98b..f9e11e59b 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -176,8 +176,6 @@ void process_configfile( char* configFile) { staticConfig.SERVER_ID = atoi(val_ptr); else if ( strcasecmp( name_ptr, "ZM_DIR_EVENTS" ) == 0 ) staticConfig.DIR_EVENTS = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_DIR_IMAGES" ) == 0 ) - staticConfig.DIR_IMAGES = std::string(val_ptr); else if ( strcasecmp( name_ptr, "ZM_DIR_SOUNDS" ) == 0 ) staticConfig.DIR_SOUNDS = std::string(val_ptr); else if ( strcasecmp( name_ptr, "ZM_DIR_EXPORTS" ) == 0 ) diff --git a/src/zm_config.h.in b/src/zm_config.h.in index 87a0f2db4..9831677f0 100644 --- a/src/zm_config.h.in +++ b/src/zm_config.h.in @@ -76,7 +76,6 @@ struct StaticConfig { std::string SERVER_NAME; unsigned int SERVER_ID; std::string DIR_EVENTS; - std::string DIR_IMAGES; std::string DIR_SOUNDS; std::string DIR_EXPORTS; std::string PATH_ZMS; diff --git a/web/ajax/zone.php b/web/ajax/zone.php index bfa77a922..12a68f681 100644 --- a/web/ajax/zone.php +++ b/web/ajax/zone.php @@ -9,37 +9,6 @@ elseif ( !isset($_REQUEST['zid']) ) ajaxError( 'No zone id(s) supplied' ); } -if ( canView( 'Monitors' ) ) -{ - switch ( $_REQUEST['action'] ) - { - case "zoneImage" : - { - $wd = getcwd(); - chdir( ZM_DIR_IMAGES ); - $hiColor = '0x00ff00'; - - $command = getZmuCommand( " -m ".$_REQUEST['mid']." -z" ); - if ( !isset($_REQUEST['zid']) ) - $_REQUEST['zid'] = 0; - $command .= "'".$_REQUEST['zid'].' '.$hiColor.' '.$_REQUEST['coords']."'"; - $status = exec( escapeshellcmd($command) ); - chdir( $wd ); - - $monitor = dbFetchOne( 'SELECT * FROM Monitors WHERE Id = ?', NULL, array($_REQUEST['mid']) ); - $points = coordsToPoints( $_REQUEST['coords'] ); - - ajaxResponse( array( - 'zoneImage' => ZM_DIR_IMAGES.'/Zones'.$monitor['Id'].'.jpg?'.time(), - 'selfIntersecting' => isSelfIntersecting( $points ), - 'area' => getPolyArea( $points ) - ) ); - - break; - } - } -} - ajaxError( 'Unrecognised action or insufficient permissions' ); ?> diff --git a/web/api/app/Controller/Component/ImageComponent.php b/web/api/app/Controller/Component/ImageComponent.php index fc967a2de..2033e0d8c 100644 --- a/web/api/app/Controller/Component/ImageComponent.php +++ b/web/api/app/Controller/Component/ImageComponent.php @@ -7,12 +7,10 @@ class ImageComponent extends Component { $captImage = sprintf( "%0".$config['ZM_EVENT_IMAGE_DIGITS']."d-capture.jpg", $frame['Frame']['FrameId'] ); $captPath = $eventPath.'/'.$captImage; - $thumbCaptPath = $config['ZM_DIR_IMAGES'].'/'.$event['Event']['Id'].'-'.$captImage; $analImage = sprintf( "%0".$config['ZM_EVENT_IMAGE_DIGITS']."d-analyse.jpg", $frame['Frame']['FrameId'] ); $analPath = $eventPath.'/'.$analImage; $analFile = $config['ZM_DIR_EVENTS']."/".$analPath; - $thumbAnalPath = $config['ZM_DIR_IMAGES'].'/'.$event['Event']['Id'].'-'.$analImage; $alarmFrame = $frame['Frame']['Type']=='Alarm'; @@ -31,8 +29,8 @@ class ImageComponent extends Component { $fraction = sprintf( "%.3f", $scale/100 ); $scale = (int)round( $scale ); - $thumbCaptPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $thumbCaptPath ); - $thumbAnalPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $thumbAnalPath ); + $thumbCaptPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $captPath ); + $thumbAnalPath = preg_replace( "/\.jpg$/", "-$scale.jpg", $analPath ); if ( $isAnalImage ) { diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php index 1d9456cc4..cf8ca8f37 100644 --- a/web/api/app/Controller/EventsController.php +++ b/web/api/app/Controller/EventsController.php @@ -318,7 +318,6 @@ class EventsController extends AppController { 'ZM_WEB_LIST_THUMB_WIDTH', 'ZM_WEB_LIST_THUMB_HEIGHT', 'ZM_EVENT_IMAGE_DIGITS', - 'ZM_DIR_IMAGES', $thumbs, 'ZM_DIR_EVENTS' ) diff --git a/web/api/app/Controller/ZonesController.php b/web/api/app/Controller/ZonesController.php index 74a87f353..4d6564443 100644 --- a/web/api/app/Controller/ZonesController.php +++ b/web/api/app/Controller/ZonesController.php @@ -137,33 +137,4 @@ class ZonesController extends AppController { return $this->flash(__('The zone could not be deleted. Please, try again.'), array('action' => 'index')); } } - - public function createZoneImage($id = null) { - $this->loadModel('Monitor'); - $this->Monitor->id = $id; - if ( !$this->Monitor->exists() ) { - throw new NotFoundException(__('Invalid zone')); - } - - $this->loadModel('Config'); - $zm_dir_images = $this->Config->find('list', array( - 'conditions' => array('Name' => 'ZM_DIR_IMAGES'), - 'fields' => array('Name', 'Value') - )); - - $zm_dir_images = $zm_dir_images['ZM_DIR_IMAGES']; - $zm_path_web = Configure::read('ZM_PATH_WEB'); - $zm_path_bin = Configure::read('ZM_PATH_BIN'); - $images_path = "$zm_path_web/$zm_dir_images"; - - chdir($images_path); - - $command = escapeshellcmd("$zm_path_bin/zmu -z -m $id"); - system($command, $status); - - $this->set(array( - 'status' => $status, - '_serialize' => array('status') - )); - } } // end class diff --git a/web/index.php b/web/index.php index bd80f1d89..2331809bc 100644 --- a/web/index.php +++ b/web/index.php @@ -164,8 +164,8 @@ $running = null; CORSHeaders(); // Check for valid content dirs -if ( !is_writable(ZM_DIR_EVENTS) || !is_writable(ZM_DIR_IMAGES) ) { - Warning("Cannot write to content dirs('".ZM_DIR_EVENTS."','".ZM_DIR_IMAGES."'). Check that these exist and are owned by the web account user"); +if ( !is_writable(ZM_DIR_EVENTS) ) { + Warning("Cannot write to event folder ".ZM_DIR_EVENTS.". Check that it exists and is owned by the web account user."); } # Globals diff --git a/web/lang/ro_ro.php b/web/lang/ro_ro.php index 1f2d17e2e..5526be753 100644 --- a/web/lang/ro_ro.php +++ b/web/lang/ro_ro.php @@ -882,10 +882,6 @@ $OLANG = array( 'Prompt' => "Directorul în care sunt stocate evenimentele", 'Help' => "Acesta este subdirectorul în care sunt salvate imaginile generate de evenimente şi alte fişiere. Implicit este un subdirector al directorului rădăcina zoneminder; dacă spaţiul nu vă permite puteţi să stocaţi imaginile pe altă partiţie, caz în care ar trebui să faceţi un link la subdirectorul implicit." ), - 'DIR_IMAGES' => array( - 'Prompt' => "Directorul în care sunt stocate imaginile", - 'Help' => "ZoneMinder generează multe imagini, majoritate asociate cu evenimente. În acest director vor fi stocate imaginile neasociate evenimentelor." - ), 'DIR_SOUNDS' => array( 'Prompt' => "Directorul cu sunetele care pot fi folosite de ZoneMinder", 'Help' => "ZoneMinder poate rula un sunet atunci când este detectată o alarmă. Acesta este directorul în care este stocat sunetul care va fi rulat." From d14e9ecf74d6d76036651a5688fbdf680bae2ec0 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Sat, 29 Dec 2018 08:53:31 -0600 Subject: [PATCH 239/240] force overloadframes and ExtendAlarmFrames to int (#2373) --- web/includes/actions.php | 8 +++++++- web/includes/functions.php | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index 2ae7fdc2a..746454bec 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -288,7 +288,13 @@ if ( !empty($_REQUEST['mid']) && canEdit('Monitors', $_REQUEST['mid']) ) { } unset( $_REQUEST['newZone']['Points'] ); - $types = array(); + + # convert these fields to integer e.g. NULL -> 0 + $types = array( + 'OverloadFrames' => 'integer', + 'ExtendAlarmFrames' => 'integer', + ); + $changes = getFormChanges($zone, $_REQUEST['newZone'], $types); if ( count($changes) ) { diff --git a/web/includes/functions.php b/web/includes/functions.php index f4a9b3395..6f2877530 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -608,6 +608,11 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) { } } break; + case 'integer' : + if ( (!isset($values[$key])) or $values[$key] != $value ) { + $changes[$key] = $key . ' = '.intval($value); + } + break; default : { if ( !isset($values[$key]) || ($values[$key] != $value) ) { From 751c312609a6c667b710e4bc4cbc0d14c9396a44 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 29 Dec 2018 09:56:33 -0500 Subject: [PATCH 240/240] fix non-ascii char --- src/zm_monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 30feecfe8..3e4aff2a4 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2646,7 +2646,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z } else { // check if end of alarm if (old_zone_alarmed) { - Debug(3, "Preclusive Zone %s alarm Ends. Prevíous score: %d", zone->Label(), old_zone_score); + Debug(3, "Preclusive Zone %s alarm Ends. Previous score: %d", zone->Label(), old_zone_score); if (old_zone_score > 0) { zone->SetExtendAlarmCount(zone->GetExtendAlarmFrames()); }