From f4ddc0fe9b0ea557ea46d9c3416e48a9ec7e022e Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 22 Oct 2018 16:13:12 -0400
Subject: [PATCH 031/240] ob_clcean and flush break outputting the image
---
web/views/image.php | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/web/views/image.php b/web/views/image.php
index 552b81256..ed54a3735 100644
--- a/web/views/image.php
+++ b/web/views/image.php
@@ -69,6 +69,7 @@ if ( empty($_REQUEST['path']) ) {
}
if ( !empty($_REQUEST['eid']) ) {
+Logger::Debug("Loading by eid");
$Event = Event::find_one(array('Id'=>$_REQUEST['eid']));
if ( !$Event ) {
header('HTTP/1.0 404 Not Found');
@@ -119,6 +120,7 @@ Logger::Debug("Got virtual frame from Bulk Frames previous delta: " . $previousB
}
// Frame can be non-existent. We have Bulk frames. So now we should try to load the bulk frame
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
+Logger::Debug("Path: $path");
}
} else {
@@ -208,12 +210,14 @@ if ( !empty($_REQUEST['scale']) ) {
$width = 0;
if ( !empty($_REQUEST['width']) ) {
+Logger::Debug("Setting width: " . $_REQUEST['width']);
if ( is_numeric($_REQUEST['width']) ) {
$x = $_REQUEST['width'];
if ( $x >= 10 and $x <= 8000 )
$width = $x;
}
}
+
$height = 0;
if ( !empty($_REQUEST['height']) ) {
if ( is_numeric($_REQUEST['height']) ) {
@@ -229,14 +233,12 @@ if ( $errorText ) {
# Clears the output buffer. Not sure what is there, but have had troubles.
ob_end_clean();
header('Content-type: image/jpeg');
- if ( ( $scale==0 || $scale==100 ) && $width==0 && $height==0 ) {
+ if ( ( $scale==0 || $scale==100 ) && ($width==0) && ($height==0) ) {
# This is so that Save Image As give a useful filename
if ( $Event ) {
$filename = $Event->MonitorId().'_'.$Event->Id().'_'.$Frame->FrameId().'.jpg';
header('Content-Disposition: inline; filename="' . $filename . '"');
}
- ob_clean();
- flush();
if ( !readfile($path) ) {
Error('No bytes read from '. $path);
}
@@ -254,6 +256,7 @@ if ( $errorText ) {
$width = ($height * $oldWidth) / $oldHeight;
} elseif ( $width != 0 && $height == 0 ) {
$height = ($width * $oldHeight) / $oldWidth;
+Logger::Debug("Figuring out height using width: $height = ($width * $oldHeight) / $oldWidth");
}
if ( $width == $oldWidth && $height == $oldHeight ) {
Warning('No change to width despite scaling.');
@@ -266,8 +269,6 @@ if ( $errorText ) {
$filename = $Event->MonitorId().'_'.$Event->Id().'_'.$Frame->FrameId()."-${width}x${height}.jpg";
header('Content-Disposition: inline; filename="' . $filename . '"');
}
- //ob_clean();
- //flush();
if ( !( file_exists($scaled_path) and readfile($scaled_path) ) ) {
Logger::Debug("Cached scaled image does not exist at $scaled_path or is no good.. Creating it");
ob_start();
From 86b0e4ea188a018079a759908575630e99e103ff Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 22 Oct 2018 18:32:39 -0400
Subject: [PATCH 032/240] fix auth_hash. Should use generateAuthHash instead
of accessing session directly
---
web/skins/classic/js/skin.js.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/web/skins/classic/js/skin.js.php b/web/skins/classic/js/skin.js.php
index f072a911e..b15ff51a5 100644
--- a/web/skins/classic/js/skin.js.php
+++ b/web/skins/classic/js/skin.js.php
@@ -55,7 +55,7 @@ if ( ! empty($refreshParent) ) {
?>;
var closePopup = ";
var auth_hash;
-auth_hash = '';
+auth_hash = '';
From 18850d8779ebff0ce65e282189afb3e74531d367 Mon Sep 17 00:00:00 2001
From: raTmole
Date: Tue, 23 Oct 2018 14:58:07 +0300
Subject: [PATCH 033/240] API getVersion Fix -> Undefined variable:
eTagMatches... (#2268)
see https://github.com/cakephp/cakephp/issues/12536
---
web/api/lib/Cake/Network/CakeResponse.php | 3 +++
1 file changed, 3 insertions(+)
diff --git a/web/api/lib/Cake/Network/CakeResponse.php b/web/api/lib/Cake/Network/CakeResponse.php
index 21dfd7b2e..982398e87 100644
--- a/web/api/lib/Cake/Network/CakeResponse.php
+++ b/web/api/lib/Cake/Network/CakeResponse.php
@@ -1168,6 +1168,9 @@ class CakeResponse {
if ($modifiedSince) {
$timeMatches = strtotime($this->modified()) === strtotime($modifiedSince);
}
+ if (!isset($etagMatches, $timeMatches)) {
+ return false;
+ }
$checks = compact('etagMatches', 'timeMatches');
if (empty($checks)) {
return false;
From 2024df43931754b5b2088f91074f98ac26b5c933 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 24 Oct 2018 09:49:56 -0400
Subject: [PATCH 034/240] use json_encode/decode instead of
serialize/unserialize to pass onvif probe results around. Also clean up some
code/ add some missing things. Fixes #2271 and #2272
---
web/lang/en_gb.php | 1 +
web/skins/classic/views/monitor.php | 2 +-
web/skins/classic/views/onvifprobe.php | 118 ++++++++++++-------------
3 files changed, 60 insertions(+), 61 deletions(-)
diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php
index 0fca2f81d..5412b94cd 100644
--- a/web/lang/en_gb.php
+++ b/web/lang/en_gb.php
@@ -237,6 +237,7 @@ $SLANG = array(
'Cause' => 'Cause',
'CheckMethod' => 'Alarm Check Method',
'ChooseDetectedCamera' => 'Choose Detected Camera',
+ 'ChooseDetectedProfile' => 'Choose Detected Profile',
'ChooseFilter' => 'Choose Filter',
'ChooseLogFormat' => 'Choose a log format',
'ChooseLogSelection' => 'Choose a log selection',
diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php
index fa2ebd44f..193b08d36 100644
--- a/web/skins/classic/views/monitor.php
+++ b/web/skins/classic/views/monitor.php
@@ -173,7 +173,7 @@ if ( !empty($_REQUEST['preset']) ) {
}
}
if ( !empty($_REQUEST['probe']) ) {
- $probe = unserialize(base64_decode($_REQUEST['probe']));
+ $probe = json_decode(base64_decode($_REQUEST['probe']));
foreach ( $probe as $name=>$value ) {
if ( isset($value) ) {
# Does isset handle NULL's? I don't think this code is correct.
diff --git a/web/skins/classic/views/onvifprobe.php b/web/skins/classic/views/onvifprobe.php
index f9c766846..ddbd895b6 100644
--- a/web/skins/classic/views/onvifprobe.php
+++ b/web/skins/classic/views/onvifprobe.php
@@ -18,7 +18,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
-if ( !canEdit( 'Monitors' ) ) {
+if ( !canEdit('Monitors') ) {
$view = 'error';
return;
}
@@ -73,26 +73,26 @@ function probeCameras( $localIp ) {
} elseif ( $tokens[1] == 'location' ) {
// $camera['location'] = $tokens[2];
} else {
- Logger::Debug('Unknown token ' . $tokens[1] );
+ Logger::Debug('Unknown token ' . $tokens[1]);
}
}
} // end foreach token
$cameras[] = $camera;
}
} // end foreach line
- }
- return( $cameras );
-}
+ } // end if results from execOnvif
+ return $cameras;
+} // end function probeCameras
function probeProfiles( $device_ep, $soapversion, $username, $password ) {
$profiles = array();
if ( $lines = @execONVIF( "profiles $device_ep $soapversion $username $password" ) ) {
foreach ( $lines as $line ) {
$line = rtrim( $line );
- if ( preg_match( '|^(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+)\s*$|', $line, $matches ) ) {
+ if ( preg_match('|^(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+)\s*$|', $line, $matches) ) {
$stream_uri = $matches[7];
// add user@pass to URI
- if ( preg_match( '|^(\S+://)(.+)$|', $stream_uri, $tokens ) ) {
+ if ( preg_match('|^(\S+://)(.+)$|', $stream_uri, $tokens) ) {
$stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2];
}
@@ -106,17 +106,15 @@ function probeProfiles( $device_ep, $soapversion, $username, $password ) {
'Profile' => $matches[1],
'Name' => $matches[2],
'Encoding' => $matches[3],
-
);
$profiles[] = $profile;
} else {
Logger::Debug("Line did not match preg: $line");
}
- }
- }
- return( $profiles );
-}
-
+ } // end foreach line
+ } // end if results from execONVIF
+ return $profiles;
+} // end function probeProfiles
//==== STEP 1 ============================================================
@@ -124,20 +122,20 @@ $focusWindow = true;
xhtmlHeaders(__FILE__, translate('MonitorProbe') );
-if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) {
+if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
$monitors = array();
- foreach ( dbFetchAll( "select Id, Name, Host from Monitors where Type = 'Remote' order by Host" ) as $monitor ) {
- if ( preg_match( '/^(.+)@(.+)$/', $monitor['Host'], $matches ) ) {
- //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])." ";
- $monitors[gethostbyname($matches[2])] = $monitor;
- } else {
- //echo "2: ".$monitor['Host']." = ".gethostbyname($monitor['Host'])." ";
- $monitors[gethostbyname($monitor['Host'])] = $monitor;
- }
+ foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type = 'Remote' ORDER BY Host") as $monitor ) {
+ if ( preg_match( '/^(.+)@(.+)$/', $monitor['Host'], $matches ) ) {
+ //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])." ";
+ $monitors[gethostbyname($matches[2])] = $monitor;
+ } else {
+ //echo "2: ".$monitor['Host']." = ".gethostbyname($monitor['Host'])." ";
+ $monitors[gethostbyname($monitor['Host'])] = $monitor;
+ }
}
- $detcameras = probeCameras( '' );
+ $detcameras = probeCameras('');
foreach ( $detcameras as $camera ) {
if ( preg_match( '|([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|', $camera['monitor']['Host'], $matches ) ) {
$ip = $matches[1];
@@ -157,13 +155,13 @@ if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) {
}
*/
// $sourceDesc = htmlspecialchars(serialize($camera['monitor']));
- $sourceDesc = base64_encode(serialize($camera['monitor']));
- $sourceString = $camera['model'].' @ '.$host . ' using version ' . $camera['monitor']['SOAP'] ;
- $cameras[$sourceDesc] = $sourceString;
+ $sourceDesc = base64_encode(json_encode($camera['monitor']));
+ $sourceString = $camera['model'].' @ '.$host . ' using version ' . $camera['monitor']['SOAP'] ;
+ $cameras[$sourceDesc] = $sourceString;
}
if ( count($cameras) <= 0 )
- $cameras[0] = translate('NoDetectedCameras');
+ $cameras[0] = translate('NoDetectedCameras');
?>
@@ -180,22 +178,23 @@ if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) {
-
+
+ 'configureButtons(this)')); ?>
-
+
-
+
-
+
@@ -205,44 +204,42 @@ if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) {
$value ) {
- if ( isset($value) ) {
- $monitor[$name] = $value;
- }
+ if ( isset($value) ) {
+ $monitor[$name] = $value;
+ }
}
$camera['monitor'] = $monitor;
//print $monitor['Host'].", ".$_REQUEST['username'].", ".$_REQUEST['password']." ";
- $detprofiles = probeProfiles( $monitor['Host'], $monitor['SOAP'], $_REQUEST['username'], $_REQUEST['password']);
+ $detprofiles = probeProfiles($monitor['Host'], $monitor['SOAP'], $_REQUEST['username'], $_REQUEST['password']);
foreach ( $detprofiles as $profile ) {
- $monitor = $camera['monitor'];
-
- $sourceString = "${profile['Name']} : ${profile['Encoding']}" .
- " (${profile['Width']}x${profile['Height']} @ ${profile['MaxFPS']}fps)";
- // copy technical details
- $monitor['Width'] = $profile['Width'];
- $monitor['Height'] = $profile['Height'];
-// The maxfps fields do not work for ip streams. Can re-enable if that is fixed.
-// $monitor['MaxFPS'] = $profile['MaxFPS'];
-// $monitor['AlarmMaxFPS'] = $profile['AlarmMaxFPS'];
- $monitor['Path'] = $profile['Path'];
-// $sourceDesc = htmlspecialchars(serialize($monitor));
- $sourceDesc = base64_encode(serialize($monitor));
- $profiles[$sourceDesc] = $sourceString;
+ $monitor = $camera['monitor'];
+
+ $sourceString = "${profile['Name']} : ${profile['Encoding']}" .
+ " (${profile['Width']}x${profile['Height']} @ ${profile['MaxFPS']}fps)";
+ // copy technical details
+ $monitor['Width'] = $profile['Width'];
+ $monitor['Height'] = $profile['Height'];
+ // The maxfps fields do not work for ip streams. Can re-enable if that is fixed.
+ // $monitor['MaxFPS'] = $profile['MaxFPS'];
+ // $monitor['AlarmMaxFPS'] = $profile['AlarmMaxFPS'];
+ $monitor['Path'] = $profile['Path'];
+ $sourceDesc = base64_encode(json_encode($monitor));
+ $profiles[$sourceDesc] = $sourceString;
}
if ( count($profiles) <= 0 )
- $profiles[0] = translate('NoDetectedProfiles');
+ $profiles[0] = translate('NoDetectedProfiles');
?>
@@ -254,17 +251,18 @@ else if($_REQUEST['step'] == "2")
-
+
-
+
+ 'configureButtons(this)')); ?>
-
+
-
+
@@ -272,5 +270,5 @@ else if($_REQUEST['step'] == "2")
From 115141bf9f13c2b7272f00651f7b6a0748059026 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 24 Oct 2018 10:02:42 -0400
Subject: [PATCH 035/240] add caching to Group::find
---
web/includes/Group.php | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/web/includes/Group.php b/web/includes/Group.php
index df9fd611e..6c8338a55 100644
--- a/web/includes/Group.php
+++ b/web/includes/Group.php
@@ -95,13 +95,12 @@ class Group {
}
}
} # end if options
- $groups = array();
- $result = dbQuery($sql, $values);
- $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Group');
- foreach ( $results as $row => $obj ) {
- $groups[] = $obj;
+
+ $results = dbFetchAll($sql, NULL, $values);
+ if ( $results ) {
+ return array_map( function($row){ return new Group($row); }, $results );
}
- return $groups;
+ return array();
} # end find()
public static function find_one($parameters = null, $options = null) {
From bca2b305183470c56de7342f416b635620265f49 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 24 Oct 2018 13:45:33 -0400
Subject: [PATCH 036/240] Add a test for channel layout and correct it if not
set
---
src/zm_videostore.cpp | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index a1c52353c..a3b66646b 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -248,18 +248,18 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
// Copy params from instream to ctx
ret = avcodec_parameters_to_context(audio_out_ctx,
audio_in_stream->codecpar);
- if (ret < 0) {
- Error("Unable to copy audio params to ctx %s\n",
+ if ( ret < 0 ) {
+ Error("Unable to copy audio params to ctx %s",
av_make_error_string(ret).c_str());
}
ret = avcodec_parameters_from_context(audio_out_stream->codecpar,
audio_out_ctx);
- if (ret < 0) {
- Error("Unable to copy audio params to stream %s\n",
+ if ( ret < 0 ) {
+ Error("Unable to copy audio params to stream %s",
av_make_error_string(ret).c_str());
}
- if (!audio_out_ctx->codec_tag) {
+ if ( !audio_out_ctx->codec_tag ) {
audio_out_ctx->codec_tag = av_codec_get_tag(
oc->oformat->codec_tag, audio_in_ctx->codec_id);
Debug(2, "Setting audio codec tag to %d",
@@ -271,12 +271,12 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
ret = avcodec_copy_context(audio_out_ctx, audio_in_ctx);
audio_out_ctx->codec_tag = 0;
#endif
- if (ret < 0) {
- Error("Unable to copy audio ctx %s\n",
+ if ( ret < 0 ) {
+ Error("Unable to copy audio ctx %s",
av_make_error_string(ret).c_str());
audio_out_stream = NULL;
} else {
- if (audio_out_ctx->channels > 1) {
+ if ( audio_out_ctx->channels > 1 ) {
Warning("Audio isn't mono, changing it.");
audio_out_ctx->channels = 1;
} else {
@@ -286,7 +286,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
} // end if audio_out_stream
} // end if is AAC
- if (audio_out_stream) {
+ if ( audio_out_stream ) {
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
@@ -522,8 +522,8 @@ bool VideoStore::setup_resampler() {
// 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\n");
+ if ( !audio_out_ctx ) {
+ Error("could not allocate codec ctx for AAC");
audio_out_stream = NULL;
return false;
}
@@ -546,6 +546,13 @@ bool VideoStore::setup_resampler() {
#else
audio_out_ctx->refcounted_frames = 1;
#endif
+ if ( ! audio_out_ctx->channel_layout ) {
+ Debug(3, "Correcting channel layout from (%d) to (%d)",
+ audio_out_ctx->channel_layout,
+ av_get_default_channel_layout(audio_out_ctx->channels)
+ );
+ audio_out_ctx->channel_layout = av_get_default_channel_layout(audio_out_ctx->channels);
+ }
if (audio_out_codec->supported_samplerates) {
int found = 0;
From d0080684b889ac4dbc4d30721681979ad175e573 Mon Sep 17 00:00:00 2001
From: Damir Merdan <44159556+dado-ca@users.noreply.github.com>
Date: Wed, 24 Oct 2018 19:52:32 +0200
Subject: [PATCH 037/240] Bosnian translation (#2266)
* Zoneminder bosnian translation
Hi,
this is a bosnian translation for zoneminder, but it can be used as croatian and serbian translation too
* Delete BA_ba.php
* Bosnian translation
80% translated, tested on my Zoneminder v1.30.4 installation and is looking good. ZmNinja also translated into Bosnian lagnuage.
---
web/lang/ba_ba.php | 995 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 995 insertions(+)
create mode 100644 web/lang/ba_ba.php
diff --git a/web/lang/ba_ba.php b/web/lang/ba_ba.php
new file mode 100644
index 000000000..e60e69066
--- /dev/null
+++ b/web/lang/ba_ba.php
@@ -0,0 +1,995 @@
+ 'Dnevnik',
+ 'DateTime' => 'Datum/Vrijeme',
+ 'Component' => 'Komponenta',
+ 'Pid' => 'PID',
+ 'Level' => 'Nivo',
+ 'Message' => 'Poruka',
+ 'Line' => 'Linija',
+ 'More' => 'Više',
+ 'Clear' => 'Očisti',
+ '24BitColour' => '24 bitne boje',
+ '32BitColour' => '32 bitne boje',
+ '8BitGrey' => '8 bit siva nijansa',
+ 'Action' => 'Action',
+ 'Actual' => 'Stvarno',
+ 'AddNewControl' => 'Dodaj kontrolu',
+ 'AddNewMonitor' => 'Dodaj monitor',
+ 'AddNewServer' => 'Dodaj novi server',
+ 'AddNewStorage' => 'Dodaj novi disk',
+ 'AddNewUser' => 'Dodaj novog korisnika',
+ 'AddNewZone' => 'Dodaj novu zonu',
+ 'Alarm' => 'Alarm',
+ 'AlarmBrFrames' => 'Alarm Sličice',
+ 'AlarmFrame' => 'Alarm sličica',
+ 'AlarmFrameCount' => 'Brzina snimanja alarma (u frejmovima)',
+ 'AlarmLimits' => 'Alarm limiti',
+ 'AlarmMaximumFPS' => 'Alarm Max SPS',
+ 'AlarmPx' => 'Alarm Px',
+ 'AlarmRefImageBlendPct' => 'Alarm Reference Image Blend %ge',
+ 'AlarmRGBUnset' => 'Morate postaviti RGB boju za alarm',
+ 'Alert' => 'Uzbuna',
+ 'All' => 'Sve',
+ 'AnalysisFPS' => 'Analiza frejmova',
+ 'AnalysisUpdateDelay' => 'Analysis Update Delay',
+ 'Apply' => 'Primjeni',
+ 'ApplyingStateChange' => 'Primjenjujem promjenu stanja',
+ 'ArchArchived' => 'Samo arhivirano',
+ 'Archive' => 'Arhiva',
+ 'Archived' => 'Ahivirano',
+ 'ArchUnarchived' => 'Samo nearhivirano',
+ 'Area' => 'Oblast',
+ 'AreaUnits' => 'Oblast (px/%)',
+ 'AttrAlarmFrames' => 'Alarm frejmovi',
+ 'AttrArchiveStatus' => 'Status arhive',
+ 'AttrAvgScore' => 'Prosj. score',
+ 'AttrCause' => 'Uzrok',
+ 'AttrStartDate' => 'Pocetni datum',
+ 'AttrEndDate' => 'Krajnji datum',
+ 'AttrStartDateTime' => 'Pocetni Datum/Vrijeme',
+ 'AttrEndDateTime' => 'Krajnji Datum/Vrijeme',
+ 'AttrDiskSpace' => 'Disk prostor',
+ 'AttrDiskBlocks' => 'Disk blokovi',
+ 'AttrDiskPercent' => 'Disk procentualno',
+ 'AttrDuration' => 'Trajanje',
+ 'AttrFrames' => 'Frejmovi',
+ 'AttrId' => 'Id',
+ 'AttrMaxScore' => 'Max. Score',
+ 'AttrMonitorId' => 'ID Kamere',
+ 'AttrMonitorName' => 'Naziv Kamere',
+ 'AttrStorageArea' => 'Storage Area',
+ 'AttrFilterServer' => 'Server Filter je pokrenut na',
+ 'AttrMonitorServer' => 'Server Monitor je pokrenut na',
+ 'AttrStorageServer' => 'Server Hosting Storage',
+ 'AttrStateId' => 'Status',
+ 'AttrName' => 'Naziv',
+ 'AttrNotes' => 'Bilješke',
+ 'AttrSystemLoad' => 'Opterećenje sistema',
+ 'AttrStartTime' => 'Vrijeme početka',
+ 'AttrEndTime' => 'Vrijeme završetka',
+ 'AttrTotalScore' => 'Ukupan score',
+ 'AttrStartWeekday' => 'Početni dan',
+ 'AttrEndWeekday' => 'Krajnji dan',
+ 'Auto' => 'Automatski',
+ 'AutoStopTimeout' => 'Auto Stop Timeout',
+ 'Available' => 'Dostupno',
+ 'AvgBrScore' => 'Avg. Score',
+ 'Available' => 'Dostupno',
+ 'Background' => 'Pozadina',
+ 'BackgroundFilter' => 'Pokreni filter u pozadini',
+ 'BadAlarmFrameCount' => 'Brojač alarm frejmova mora biti tipa integer počevši od jedan ili više',
+ 'BadAlarmMaxFPS' => 'Max FPS za alarm mora biti pozitivan cjeli broj ili broj sa pomičnim zarezom',
+ 'BadAnalysisFPS' => 'Broj frejmova za analitiku mora pozitivan cjeli broj ili broj sa pomičnim zarezom',
+ 'BadAnalysisUpdateDelay'=> 'Vrijeme zadrške analitike mora biti broj od nula ili više',
+ 'BadChannel' => 'Kanal mora biti postavljen na cjeli broj nula ili više',
+ 'BadDevice' => 'Uredaj mora biti postavljen na validnu vrijednost',
+ 'BadFormat' => 'Format mora biti postavljen na validnu vrijenost',
+ 'BadFPSReportInterval' => 'FPS report interval buffer count must be an integer of 0 or more',
+ 'BadFrameSkip' => 'Frame skip count must be an integer of zero or more',
+ 'BadMotionFrameSkip' => 'Motion Frame skip count must be an integer of zero or more',
+ 'BadHeight' => 'Height must be set to a valid value',
+ 'BadHost' => 'Host must be set to a valid ip address or hostname, do not include http://',
+ 'BadImageBufferCount' => 'Image buffer size must be an integer of 10 or more',
+ 'BadLabelX' => 'Label X co-ordinate must be set to an integer of zero or more',
+ 'BadLabelY' => 'Label Y co-ordinate must be set to an integer of zero or more',
+ 'BadMaxFPS' => 'Maximum FPS must be a positive integer or floating point value',
+ 'BadNameChars' => 'Names may only contain alphanumeric characters plus spaces, hyphen and underscore',
+ 'BadPalette' => 'Palette must be set to a valid value',
+ 'BadColours' => 'Target colour must be set to a valid value',
+ 'BadPath' => 'Path must be set to a valid value',
+ 'BadPort' => 'Port must be set to a valid number',
+ 'BadPostEventCount' => 'Post event image count must be an integer of zero or more',
+ 'BadPreEventCount' => 'Pre event image count must be at least zero, and less than image buffer size',
+ 'BadRefBlendPerc' => 'Reference blend percentage must be a positive integer',
+ 'BadSectionLength' => 'Section length must be an integer of 30 or more',
+ 'BadSignalCheckColour' => 'Signal check colour must be a valid RGB colour string',
+ 'BadStreamReplayBuffer' => 'Stream replay buffer must be an integer of zero or more',
+ 'BadSourceType' => 'Source Type \"Web Site\" requires the Function to be set to \"Monitor\"',
+ 'BadWarmupCount' => 'Warmup frames must be an integer of zero or more',
+ 'BadWebColour' => 'Web colour must be a valid web colour string',
+ 'BadWebSitePath' => 'Please enter a complete website url, including the http:// or https:// prefix.',
+ 'BadWidth' => 'Width must be set to a valid value',
+ 'Bandwidth' => 'Propusnost',
+ 'BandwidthHead' => 'propusnost', // This is the end of the bandwidth status on the top of the console, different in many language due to phrasing
+ 'BlobPx' => 'Blob Px',
+ 'Blobs' => 'Blobs',
+ 'BlobSizes' => 'Blob velicine',
+ 'Brightness' => 'Svjetloća',
+ 'Buffer' => 'Bufer',
+ 'Buffers' => 'Buferi',
+ 'CanAutoFocus' => 'Podržava Auto fokusiranje',
+ 'CanAutoGain' => 'Podržava Auto pojačanje',
+ 'CanAutoIris' => 'Podržava Auto blenda',
+ 'CanAutoWhite' => 'Podržava Auto balans bijel.',
+ 'CanAutoZoom' => 'Podržava Auto zum',
+ 'Cancel' => 'otkaži',
+ 'CancelForcedAlarm' => 'Otkaži prisilni alarm',
+ 'CanFocusAbs' => 'Podržava Abs fokus',
+ 'CanFocus' => 'Podržava Fokus',
+ 'CanFocusCon' => 'Podržava Kontinuirani fokus',
+ 'CanFocusRel' => 'Podržava Relativni fokus',
+ 'CanGainAbs' => 'Podržava Aps. pojačanje',
+ 'CanGain' => 'Podržava Pojačanje ',
+ 'CanGainCon' => 'Podržava Kontinuirano pojačanje',
+ 'CanGainRel' => 'Podržava Relativno pojačanje',
+ 'CanIrisAbs' => 'Podržava Aps. blenda',
+ 'CanIris' => 'Podržava Blenda',
+ 'CanIrisCon' => 'Podržava kontinuirana blenda',
+ 'CanIrisRel' => 'Podržava Relativna blenda',
+ 'CanMoveAbs' => 'Podržava Aps. kretanje',
+ 'CanMove' => 'Podržava Kretanje',
+ 'CanMoveCon' => 'Podržava Kontinuirano kretanje',
+ 'CanMoveDiag' => 'Podržava Dijagonalno kretanje',
+ 'CanMoveMap' => 'Podržava Mapirano kretanje',
+ 'CanMoveRel' => 'Podržava Relativno kretanje',
+ 'CanPan' => 'Podržava Pomak' ,
+ 'CanReset' => 'PodržavaReset',
+ 'CanSetPresets' => 'Podržava presetove',
+ 'CanSleep' => 'Podržava Sleep',
+ 'CanTilt' => 'Podržava nagib',
+ 'CanWake' => 'Podržava Wake',
+ 'CanWhiteAbs' => 'Podržava Aps. balans bijele boje',
+ 'CanWhiteBal' => 'Podržava balans bijel.',
+ 'CanWhite' => 'Podržava bijelu',
+ 'CanWhiteCon' => 'Podržava kont. balans bijele boje',
+ 'CanWhiteRel' => 'Podržava relativ. balans bijele boje',
+ 'CanZoomAbs' => 'Podržava Aps. zoom',
+ 'CanZoom' => 'Podržava Zoom',
+ 'CanZoomCon' => 'Podržava kontinuirani Zoom',
+ 'CanZoomRel' => 'Podržava Relativni zoom',
+ 'CaptureHeight' => 'Visina slike',
+ 'CaptureMethod' => 'Metoda snimanja',
+ 'CaptureResolution' => 'Snimi rezoluciju',
+ 'CapturePalette' => 'Paleta boja',
+ 'CaptureWidth' => 'Širina slike',
+ 'Cause' => 'Uzrok',
+ 'CheckMethod' => 'Metoda provjere alarma',
+ 'ChooseDetectedCamera' => 'Odaberi otkrivenu kameru',
+ 'ChooseFilter' => 'Odaberi filter',
+ 'ChooseLogFormat' => 'Odaberi dugi format',
+ 'ChooseLogSelection' => 'Odaberi dugu selekciju',
+ 'ChoosePreset' => 'Odaberi preset',
+ 'CloneMonitor' => 'Kloniraj',
+ 'Close' => 'Zatvori',
+ 'Colour' => 'Bojs',
+ 'Command' => 'Komanda',
+ 'ConcurrentFilter' => 'Istovremeno pokreni filter',
+ 'Config' => 'Postavke',
+ 'ConfiguredFor' => 'Podešeno za',
+ 'ConfirmDeleteEvents' => 'Sigurni ste da želite izbrisati odabrane događaje?',
+ 'ConfirmPassword' => 'Potvrdi lozinku',
+ 'ConjAnd' => 'i',
+ 'ConjOr' => 'ili',
+ 'Console' => 'Konzola',
+ 'ContactAdmin' => 'Molimo konkatirajte svog administratora za detalje.',
+ 'Continue' => 'Nastavi',
+ 'Contrast' => 'Kontrast',
+ 'ControlAddress' => 'Kontrolna adresa',
+ 'ControlCap' => 'Control Capability',
+ 'ControlCaps' => 'Control Capabilities',
+ 'Control' => 'PTZ kontole',
+ 'ControlDevice' => 'Kontroliši uređaj',
+ 'Controllable' => 'Moguće kontrolisati',
+ 'ControlType' => 'Tipa kontrole',
+ 'Current' => 'Tekuće',
+ 'Cycle' => 'Kruži',
+ 'CycleWatch' => 'Kružni prikaz',
+ 'Day' => 'Dan',
+ 'Debug' => 'Debug',
+ 'DefaultRate' => 'Podrazumjevana stopa',
+ 'DefaultScale' => 'Podrazumjevani razmjer',
+ 'DefaultView' => 'Podrazumjevani prikaz',
+ 'Deinterlacing' => 'Deinterlacing',
+ 'RTSPDescribe' => 'Use RTSP Response Media URL',
+ 'Delay' => 'Zadrška',
+ 'DeleteAndNext' => 'Izbriši & Sljedeće',
+ 'DeleteAndPrev' => 'Izbriši & Preth',
+ 'Delete' => 'Izbriši',
+ 'DeleteSavedFilter' => 'Izbriši spremljeni filter',
+ 'Description' => 'Opis',
+ 'DetectedCameras' => 'Detektovane kamere:',
+ 'DetectedProfiles' => 'Otkriveni profili',
+ 'DeviceChannel' => 'Kanal',
+ 'DeviceFormat' => 'Sistem boja',
+ 'DeviceNumber' => 'Broj uređaja',
+ 'DevicePath' => 'Putanja uređaja',
+ 'Device' => 'Uređaj',
+ 'Devices' => 'Uređaji',
+ 'Dimensions' => 'Dimenzije',
+ 'DisableAlarms' => 'Onemogući alarme',
+ 'Disk' => 'Disk',
+ 'Display' => 'Prikaz',
+ 'Displaying' => 'Prikazujem',
+ 'DonateAlready' => 'Ne, već sam napravio donaciju.',
+ 'DonateEnticement' => 'You\'ve been running ZoneMinder for a while now and hopefully are finding it a useful addition to your home or workplace security. Although ZoneMinder is, and will remain, free and open source, it costs money to develop and support. If you would like to help support future development and new features then please consider donating. Donating is, of course, optional but very much appreciated and you can donate as much or as little as you like.
If you would like to donate please select the option below or go to http://www.zoneminder.com/donate.html in your browser.
Thank you for using ZoneMinder and don\'t forget to visit the forums on ZoneMinder.com for support or suggestions about how to make your ZoneMinder experience even better.',
+ 'Donate' => 'Molimo donirajte',
+ 'DonateRemindDay' => 'Ne još, podsjetime za 1 dan',
+ 'DonateRemindHour' => 'Ne još, podsjetime za 1 sat',
+ 'DonateRemindMonth' => 'Ne još, podsjeti me za jedan mjesec',
+ 'DonateRemindNever' => 'Ne, ne želim donirati, nemoj me više podsjećati.',
+ 'DonateRemindWeek' => 'Ne još, podsjeti me za sedam dana.',
+ 'DonateYes' => 'Da, želim da doniram sada.',
+ 'DoNativeMotionDetection'=> 'Nativna detekcija pokreta',
+ 'Download' => 'Preuzmi',
+ 'DuplicateMonitorName' => 'Dupliciraj ime monitora',
+ 'Duration' => 'Trajanje',
+ 'Edit' => 'Uredi',
+ 'EditLayout' => 'Uredi raspored',
+ 'Email' => 'Email',
+ 'EnableAlarms' => 'Omogući alarme',
+ 'Enabled' => 'Omogućeno',
+ 'EnterNewFilterName' => 'Unesi novo ime za filter',
+ 'ErrorBrackets' => 'Greška, provjerite da li imate jednak broj otvorenih i zatvorenih zagrada.',
+ 'Error' => 'Greška',
+ 'ErrorValidValue' => 'Greška, osigurajte se da svi pojmovi imaju valide vrijednosti',
+ 'Etc' => 'itd',
+ 'Event' => 'Događaj',
+ 'EventFilter' => 'Filter događaja',
+ 'EventId' => 'ID događaja',
+ 'EventName' => 'Naziv događaja',
+ 'EventPrefix' => 'Prefiks događaja',
+ 'Events' => 'Događaji',
+ 'Exclude' => 'Isključi',
+ 'Execute' => 'Izvrši',
+ 'ExportDetails' => 'Izvezi detalje o događaju',
+ 'Exif' => 'Umetni EXIF podatke u sliku',
+ 'Export' => 'Izvezi',
+ 'DownloadVideo' => 'Preuzmi video',
+ 'GenerateDownload' => 'Generiši preuzimanje',
+ 'ExportFailed' => 'Izvoz nije uspio',
+ 'ExportFormat' => 'Format za izvoz',
+ 'ExportFormatTar' => 'Tar',
+ 'ExportFormatZip' => 'Zip',
+ 'ExportFrames' => 'Izvezi detalje frejma',
+ 'ExportImageFiles' => 'Izvezi slike',
+ 'ExportLog' => 'Izvezi zapisnik',
+ 'Exporting' => 'Izvozim',
+ 'ExportMiscFiles' => 'Izvezi druge fajlove (ukoliko postoje)',
+ 'ExportOptions' => 'Opcije izvoženja',
+ 'ExportSucceeded' => 'Izvoz uspio',
+ 'ExportVideoFiles' => 'Izvezi video fileove (ukoliko postoje)',
+ 'Far' => 'Far',
+ 'FastForward' => 'Naprijed',
+ 'Feed' => 'Feed',
+ 'Ffmpeg' => 'Ffmpeg',
+ 'File' => 'File',
+ 'FilterArchiveEvents' => 'Arhiviraj pronađeno',
+ 'FilterUpdateDiskSpace' => 'Ažuriraj korišteni prostor na disku',
+ 'FilterDeleteEvents' => 'Izbriši sve pronađeno',
+ 'FilterMoveEvents' => 'Premjesti pronađeno',
+ 'FilterEmailEvents' => 'Pošalji detalje mailom',
+ 'FilterExecuteEvents' => 'Izvrši sljededeću komandu',
+ 'FilterLog' => 'Filtriraj zapis',
+ 'FilterMessageEvents' => 'Message details of all matches',
+ 'FilterPx' => 'Filter Px',
+ 'Filter' => 'Filter',
+ 'Filters' => 'Filteri',
+ 'FilterUnset' => 'Morate navesti širinu i visinu filtera',
+ 'FilterUploadEvents' => 'Učitaj sve događaje',
+ 'FilterVideoEvents' => 'Napravi video',
+ 'First' => 'Prvi',
+ 'FlippedHori' => 'Zaokrenuto horizontalno',
+ 'FlippedVert' => 'Zaokrenuto vertikalno',
+ 'FnNone' => 'nijedan', // Added 2013.08.16.
+ 'FnMonitor' => 'Monitor', // Added 2013.08.16.
+ 'FnModect' => 'Modect', // Added 2013.08.16.
+ 'FnRecord' => 'Record', // Added 2013.08.16.
+ 'FnMocord' => 'Mocord', // Added 2013.08.16.
+ 'FnNodect' => 'Nodect', // Added 2013.08.16.
+ 'Focus' => 'Fokus',
+ 'ForceAlarm' => 'Prisilni alarm',
+ 'Format' => 'Format',
+ 'FPS' => 'fps',
+ 'FPSReportInterval' => 'FPS Report Interval',
+ 'Frame' => 'Frame',
+ 'FrameId' => 'Frame Id',
+ 'FrameRate' => 'Frame Rate',
+ 'Frames' => 'Frejmovi',
+ 'FrameSkip' => 'Preskoči frejm',
+ 'MotionFrameSkip' => 'Motion Frame Skip',
+ 'FTP' => 'FTP',
+ 'Func' => 'Func',
+ 'Function' => 'Funkcija',
+ 'Gain' => 'Pojačanje',
+ 'General' => 'Opšte',
+ 'GenerateVideo' => 'Generiši video',
+ 'GeneratingVideo' => 'Generiši video',
+ 'GoToZoneMinder' => 'Idi na ZoneMinder.com',
+ 'Grey' => 'Siva',
+ 'Group' => 'Grupa',
+ 'Groups' => 'Grupe',
+ 'HasFocusSpeed' => 'Posjeduje brzo fokusiranja',
+ 'HasGainSpeed' => 'Posjeduje brzo pojačanja',
+ 'HasHomePreset' => 'Has Home Preset',
+ 'HasIrisSpeed' => 'Posjeduje brzu blendu',
+ 'HasPanSpeed' => 'Posjeduje brzi pomak',
+ 'HasPresets' => 'Posjeduje pre-setove',
+ 'HasTiltSpeed' => 'Posjeduje brzi nagiba',
+ 'HasTurboPan' => 'Posjeduje turbo pomak',
+ 'HasTurboTilt' => 'Posjeduje turbo nagib',
+ 'HasWhiteSpeed' => 'Posjeduje brzo podeš.bijele',
+ 'HasZoomSpeed' => 'Posjeduje brzi zoom',
+ 'HighBW' => 'High B/W',
+ 'High' => 'veliku',
+ 'Home' => 'Početna',
+ 'Hostname' => 'Hostname',
+ 'Hour' => 'Sat',
+ 'Hue' => 'Nijansa',
+ 'Id' => 'Id',
+ 'Idle' => 'Na čekanju',
+ 'Ignore' => 'Zanemari',
+ 'ImageBufferSize' => 'Veličina slikovnog bufera (u frejmovima)',
+ 'Image' => 'Slika',
+ 'Images' => 'Slike',
+ 'Include' => 'Uključi',
+ 'In' => 'U',
+ 'Inverted' => 'Invertirano',
+ 'Iris' => 'Blenda',
+ 'KeyString' => 'Key String',
+ 'Label' => 'Oznaka',
+ 'Language' => 'Jezik',
+ 'Last' => 'Zadnje',
+ 'Layout' => 'Raspored',
+ 'Libvlc' => 'Libvlc',
+ 'LimitResultsPost' => 'results only', // This is used at the end of the phrase 'Limit to first N results only'
+ 'LimitResultsPre' => 'Limit to first', // This is used at the beginning of the phrase 'Limit to first N results only'
+ 'LinkedMonitors' => 'Povezani monitori',
+ 'List' => 'Popis',
+ 'ListMatches' => 'Prikaži pronađeno',
+ 'Load' => 'Opterećenje',
+ 'Local' => 'Lokalno',
+ 'Log' => 'Zapis',
+ 'Logs' => 'Zapisi',
+ 'Logging' => 'Dnevnik događaja',
+ 'LoggedInAs' => 'Prijavljen kao',
+ 'LoggingIn' => 'Prijavljujem',
+ 'Login' => 'prijava',
+ 'Logout' => 'odjava',
+ 'LowBW' => 'Low B/W',
+ 'Low' => 'nisku',
+ 'Main' => 'Glavno',
+ 'Man' => 'Man',
+ 'Manual' => 'Ručno',
+ 'Mark' => 'Označi',
+ 'MaxBandwidth' => 'Max propusnost',
+ 'MaxBrScore' => 'Max. Score',
+ 'MaxFocusRange' => 'Max raspon fokusa',
+ 'MaxFocusSpeed' => 'Max brzina fokusa',
+ 'MaxFocusStep' => 'Max korak fokusa',
+ 'MaxGainRange' => 'Max raspon pojačanja',
+ 'MaxGainSpeed' => 'Max brzina pojačanja',
+ 'MaxGainStep' => 'Max korak pojačanja',
+ 'MaximumFPS' => 'Maximum FPS',
+ 'MaxIrisRange' => 'Max raspon blende',
+ 'MaxIrisSpeed' => 'Max brzina blende',
+ 'MaxIrisStep' => 'Max korak blende',
+ 'Max' => 'Max',
+ 'MaxPanRange' => 'Max raspon pomaka',
+ 'MaxPanSpeed' => 'Max brzina pomaka',
+ 'MaxPanStep' => 'Max korak pomaka',
+ 'MaxTiltRange' => 'Max raspon nagiba',
+ 'MaxTiltSpeed' => 'Max brzina nagiba',
+ 'MaxTiltStep' => 'Max korak nagiba',
+ 'MaxWhiteRange' => 'Max raspon bijele',
+ 'MaxWhiteSpeed' => 'Max brzina bijele',
+ 'MaxWhiteStep' => 'Max korak bijele',
+ 'MaxZoomRange' => 'Max raspon zumiranja',
+ 'MaxZoomSpeed' => 'Max brzina zumiranja',
+ 'MaxZoomStep' => 'Max korak zumiranja',
+ 'MediumBW' => 'Medium B/W',
+ 'Medium' => 'srednju',
+ 'MinAlarmAreaLtMax' => 'Min područje alarma mora biti manje od maksimalnog',
+ 'MinAlarmAreaUnset' => 'Morate zadati minimalni broj alarm piksela',
+ 'MinBlobAreaLtMax' => 'Min blob područje mora biti manje od maksimalnog',
+ 'MinBlobAreaUnset' => 'Morate zadati minimalni broj blob piksela',
+ 'MinBlobLtMinFilter' => 'Min blob oblast mora biti manja ili jednaka minimalnoj oblasti filtera',
+ 'MinBlobsLtMax' => 'Min blob mora biti manji od maksimalne',
+ 'MinBlobsUnset' => 'morate zadati minimalni broj blob-ova',
+ 'MinFilterAreaLtMax' => 'Minimalna oblast filtera mora biti manja od maksimalne',
+ 'MinFilterAreaUnset' => 'Morate zadati minimalni broj filter piksela',
+ 'MinFilterLtMinAlarm' => 'Min oblast filtera mora biti manja ili jednaka minimalnoj oblasti alarmne oblasti',
+ 'MinFocusRange' => 'Min raspon fokusiranja',
+ 'MinFocusSpeed' => 'Min brzina fokusiranja',
+ 'MinFocusStep' => 'Min korak fokusiranja',
+ 'MinGainRange' => 'Min raspon pojačanja',
+ 'MinGainSpeed' => 'Min brzina pojačanja',
+ 'MinGainStep' => 'Min korak pojačanja',
+ 'MinIrisRange' => 'Min raspon blende',
+ 'MinIrisSpeed' => 'Min brzina blende',
+ 'MinIrisStep' => 'Min korak blende',
+ 'MinPanRange' => 'Min raspon pomaka',
+ 'MinPanSpeed' => 'Min brzina pomaka',
+ 'MinPanStep' => 'Min korak pomaka',
+ 'MinPixelThresLtMax' => 'Min prag piksela mora biti manji od maksimalnog',
+ 'MinPixelThresUnset' => 'Morate zadati minimalni prag piksela',
+ 'MinTiltRange' => 'Min Tilt Range',
+ 'MinTiltSpeed' => 'Min Tilt Speed',
+ 'MinTiltStep' => 'Min Tilt Step',
+ 'MinWhiteRange' => 'Min raspon bijelog balansa',
+ 'MinWhiteSpeed' => 'Min brzina bijelog balansa',
+ 'MinWhiteStep' => 'Min White Bal. Step',
+ 'MinZoomRange' => 'Min raspon zumiranja',
+ 'MinZoomSpeed' => 'Min brzina zumiranja',
+ 'MinZoomStep' => 'Min korak zumiranja',
+ 'Misc' => 'Razno',
+ 'Mode' => 'Modus',
+ 'MonitorIds' => 'Monitor Ids',
+ 'Monitor' => 'Monitor',
+ 'MonitorPresetIntro' => 'Odaberite odgovarajuće pre-setove sa popisa.
Imajte u vidu da ovo može prepisati bilo koju vrijednost koja postoji za odabrane monitore.
',
+ 'MonitorPreset' => 'Monitor Preset',
+ 'MonitorProbeIntro' => 'Donji popis prikazuje otkrivene analogne i mrežne kamere, te da li se iste već koriste i da li su dostupne.
Odaberite željenu kameru sa donjeg popisa.
Imajte u vidu da ovo može prepisati bilo koju vrijednost koja postoji za odabrane monitore.
Please note that not all cameras may be detected and that choosing a camera here may overwrite any values you already have configured for the current monitor.
',
+ 'OnvifCredentialsIntro' => 'Please supply user name and password for the selected camera. If no user has been created for the camera then the user given here will be created with the given password.
',
+ 'Open' => 'Otvori',
+ 'OpEq' => 'jednako',
+ 'OpGtEq' => 'veće ili jednako od',
+ 'OpGt' => 'veće ',
+ 'OpIn' => 'in set',
+ 'OpLtEq' => 'manje ili jednako od',
+ 'OpLt' => 'manje od',
+ 'OpMatches' => 'matches',
+ 'OpNe' => 'nije jednako',
+ 'OpNotIn' => 'nije u ',
+ 'OpNotMatches' => 'ne poklapa se',
+ 'OpIs' => 'je',
+ 'OpIsNot' => 'nije',
+ 'OptionalEncoderParam' => 'Opcionalni parametri enkodera',
+ 'OptionHelp' => 'Option Help',
+ 'OptionRestartWarning' => 'These changes may not come into effect fully\nwhile the system is running. When you have\nfinished making your changes please ensure that\nyou restart ZoneMinder.',
+ 'Options' => 'Opcije',
+ 'Order' => 'Redosljed',
+ 'OrEnterNewName' => 'ili unesi novo ime',
+ 'Orientation' => 'Orijentacija',
+ 'Out' => 'Izlaz',
+ 'OverwriteExisting' => 'Prepiši preko postojećeg',
+ 'Paged' => 'stranično',
+ 'PanLeft' => 'Pomak lijevo',
+ 'Pan' => 'Pomak',
+ 'PanRight' => 'Pomak desno',
+ 'PanTilt' => 'Pomak/Nagib',
+ 'Parameter' => 'Parametar',
+ 'Password' => 'Lozinka',
+ 'PasswordsDifferent' => 'Nova i potvrđena lozinka se razlikuju',
+ 'Paths' => 'Putanje',
+ 'Pause' => 'Pauza',
+ 'PhoneBW' => 'Telefon B/W',
+ 'Phone' => 'Telefon',
+ 'PixelDiff' => 'Piksel razli.',
+ 'Pixels' => 'pikseli',
+ 'PlayAll' => 'play all',
+ 'Play' => 'Play',
+ 'Plugins' => 'Plugini',
+ 'PleaseWait' => 'Molim čekati',
+ 'Point' => 'Point',
+ 'PostEventImageBuffer' => 'Br. frejmova poslije događaja',
+ 'PreEventImageBuffer' => 'Br. frejmova prije događaja',
+ 'PreserveAspect' => 'Zadrži omjer',
+ 'Preset' => 'Preset',
+ 'Presets' => 'Presets',
+ 'Prev' => 'Preth',
+ 'Privacy' => 'Privatnost',
+ 'PrivacyAbout' => 'O',
+ 'PrivacyAboutText' => 'Since 2002, ZoneMinder has been the premier free and open-source Video Management System (VMS) solution for Linux platforms. ZoneMinder is supported by the community and is managed by those who choose to volunteer their spare time to the project. The best way to improve ZoneMinder is to get involved.',
+ 'PrivacyContact' => 'Konakt',
+ 'PrivacyContactText' => 'Please contact us here for any questions regarding our privacy policy or to have your information removed.
For support, there are three primary ways to engage with the community:
Our Github forum is only for bug reporting. Please use our user forum or slack channel for all other questions or comments.
',
+ 'PrivacyCookies' => 'Kolačići',
+ 'PrivacyCookiesText' => 'Whether you use a web browser or a mobile app to communicate with the ZoneMinder server, a ZMSESSID cookie is created on the client to uniquely identify a session with the ZoneMinder server. ZmCSS and zmSkin cookies are created to remember your style and skin choices.',
+ 'PrivacyTelemetry' => 'Telemetry',
+ 'PrivacyTelemetryText' => 'Because ZoneMinder is open-source, anyone can install it without registering. This makes it difficult to answer questions such as: how many systems are out there, what is the largest system out there, what kind of systems are out there, or where are these systems located? Knowing the answers to these questions, helps users who ask us these questions, and it helps us set priorities based on the majority user base.',
+ 'PrivacyTelemetryList' => 'The ZoneMinder Telemetry daemon collects the following data about your system:
A unique identifier (UUID)
City based location is gathered by querying ipinfo.io. City, region, country, latitude, and longitude parameters are saved. The latitude and longitude coordinates are accurate down to the city or town level only!
Current time
Total number of monitors
Total number of events
System architecture
Operating system kernel, distro, and distro version
Version of ZoneMinder
Total amount of memory
Number of cpu cores
',
+ 'PrivacyMonitorList' => 'The following configuration parameters from each monitor are collected:
Id
Name
Type
Function
Width
Height
Colours
MaxFPS
AlarmMaxFPS
',
+ 'PrivacyConclusionText' => 'We are NOT collecting any image specific data from your cameras. We don�t know what your cameras are watching. This data will not be sold or used for any purpose not stated herein. By clicking accept, you agree to send us this data to help make ZoneMinder a better product. By clicking decline, you can still freely use ZoneMinder and all its features.',
+ 'Probe' => 'Detektuj kameru',
+ 'ProfileProbe' => 'Stream proba',
+ 'ProfileProbeIntro' => 'The list below shows the existing stream profiles of the selected camera .
Select the desired entry from the list below.
Please note that ZoneMinder cannot configure additional profiles and that choosing a camera here may overwrite any values you already have configured for the current monitor.
',
+ 'Progress' => 'Napredak',
+ 'Protocol' => 'Protkol',
+ 'Rate' => 'Stopa',
+ 'RecaptchaWarning' => 'Your reCaptcha secret key is invalid. Please correct it, or reCaptcha will not work', // added Sep 24 2015 - PP
+ 'RecordAudio' => 'Whether to store the audio stream when saving an event.',
+ 'Real' => 'Stvarno',
+ 'Record' => 'Snimaj',
+ 'RefImageBlendPct' => 'Reference Image Blend %ge',
+ 'Refresh' => 'Osvježi',
+ 'RemoteHostName' => 'Naziv uređaja',
+ 'RemoteHostPath' => 'Putanja',
+ 'RemoteHostSubPath' => 'Pod-putanja',
+ 'RemoteHostPort' => 'Port',
+ 'RemoteImageColours' => 'Boje slike',
+ 'RemoteMethod' => 'Metoda',
+ 'RemoteProtocol' => 'Protokol',
+ 'Remote' => 'Udaljeno',
+ 'Rename' => 'Preimenuj',
+ 'ReplayAll' => 'Svi događaji',
+ 'ReplayGapless' => 'Gapless Events',
+ 'Replay' => 'Ponovo odigraj',
+ 'ReplaySingle' => 'Jedan događaj',
+ 'ReportEventAudit' => 'Audit Events Report',
+ 'ResetEventCounts' => 'Resetiraj događaje',
+ 'Reset' => 'Reset',
+ 'Restarting' => 'Restartiram',
+ 'Restart' => 'Restaruj',
+ 'RestrictedCameraIds' => 'Restricted Camera Ids',
+ 'RestrictedMonitors' => 'Ograničeni monitori',
+ 'ReturnDelay' => 'Vrati kašnjenje',
+ 'ReturnLocation' => 'Vrati lokaciju',
+ 'Rewind' => 'Premotaj',
+ 'RotateLeft' => 'Rotoraj ulijevo',
+ 'RotateRight' => 'Rotiraj udesno',
+ 'RTSPTransport' => 'RTSP Transport Protocol',
+ 'RunAudit' => 'Run Audit Process',
+ 'RunLocalUpdate' => 'Pokrenite zmupdate.pl za ažuriranje',
+ 'RunMode' => 'Modus rada',
+ 'Running' => 'Pokrenuto',
+ 'RunState' => 'Radni modus',
+ 'RunStats' => 'Pokreni stats proces',
+ 'RunTrigger' => 'Pokreni triger proces',
+ 'SaveAs' => 'Spremi kao',
+ 'SaveFilter' => 'Spremi Filter',
+ 'SaveJPEGs' => 'Spremi JPEGs',
+ 'Save' => 'Spremi',
+ 'Scale' => 'Razmjer',
+ 'Score' => 'Zbir',
+ 'Secs' => 'Secs',
+ 'Sectionlength' => 'Odaberi dužinu',
+ 'SelectMonitors' => 'SOdaberi monitore',
+ 'Select' => 'Odaberi',
+ 'SelectFormat' => 'Odaberi format',
+ 'SelectLog' => 'Odaberi zapis',
+ 'SelfIntersecting' => 'Polygon edges must not intersect',
+ 'SetNewBandwidth' => 'Postavi propusnost na',
+ 'SetPreset' => 'Postavi pozicije',
+ 'Set' => 'Postavi',
+ 'Settings' => 'Postavke',
+ 'ShowFilterWindow' => 'Prikaži prozor za filter',
+ 'ShowTimeline' => 'Prikaži vremensku liniju',
+ 'SignalCheckColour' => 'Signal Check Colour',
+ 'SignalCheckPoints' => 'Signal Check Points',
+ 'Size' => 'Veličina',
+ 'SkinDescription' => 'Izmjeni izgled za ovu sesiju',
+ 'CSSDescription' => 'Izmjeni css za ovu sesiju',
+ 'Sleep' => 'Sleep',
+ 'SortAsc' => 'Rastuće',
+ 'SortBy' => 'Sortiraj po',
+ 'SortDesc' => 'Padajuće',
+ 'Source' => 'Izvor',
+ 'SourceColours' => 'Source Colours',
+ 'SourcePath' => 'Putanja izvora ',
+ 'SourceType' => 'Izvor videa',
+ 'SpeedHigh' => 'Velika brzina',
+ 'SpeedLow' => 'Niska brzina',
+ 'SpeedMedium' => 'Srednja brzina',
+ 'Speed' => 'brzina',
+ 'SpeedTurbo' => 'Turbo brzina',
+ 'Start' => 'Start',
+ 'State' => 'Stanje',
+ 'Stats' => 'Statistka',
+ 'Status' => 'Status',
+ 'StatusUnknown' => 'Nepoznato',
+ 'StatusConnected' => 'Snimam',
+ 'StatusNotRunning' => 'Nije pokrenuto',
+ 'StatusRunning' => 'Ne snima',
+ 'StepBack' => 'Korak nazad',
+ 'StepForward' => 'Korak naprijed',
+ 'StepLarge' => 'Veliki korak',
+ 'StepMedium' => 'Srednji korak',
+ 'StepNone' => 'Bez koraka',
+ 'StepSmall' => 'Mali korak',
+ 'Step' => 'Korak',
+ 'Stills' => 'Stills',
+ 'Stopped' => 'Zaustavljeno',
+ 'Stop' => 'Zaustavi',
+ 'StorageArea' => 'Storage Area',
+ 'StorageDoDelete' => 'Brisanja',
+ 'StorageScheme' => 'Šema',
+ 'StreamReplayBuffer' => 'Stream Replay Image Buffer',
+ 'Stream' => 'Stream',
+ 'Submit' => 'Pošalji',
+ 'System' => 'Sistem',
+ 'TargetColorspace' => 'Rezolucija boja',
+ 'Tele' => 'Udaljeno',
+ 'Thumbnail' => 'Sličica',
+ 'Tilt' => 'Tilt',
+ 'TimeDelta' => 'Vremenska razlika',
+ 'Timeline' => 'Vremenska linija',
+ 'TimelineTip1' => 'Pass your mouse over the graph to view a snapshot image and event details.', // Added 2013.08.15.
+ 'TimelineTip2' => 'Click on the coloured sections of the graph, or the image, to view the event.', // Added 2013.08.15.
+ 'TimelineTip3' => 'Click on the background to zoom in to a smaller time period based around your click.', // Added 2013.08.15.
+ 'TimelineTip4' => 'Use the controls below to zoom out or navigate back and forward through the time range.', // Added 2013.08.15.
+ 'TimestampLabelFormat' => 'Timestamp format oznake',
+ 'TimestampLabelX' => 'Timestamp oznaka X',
+ 'TimestampLabelY' => 'Timestamp oznaka Y',
+ 'TimestampLabelSize' => 'Veličina fonta',
+ 'Timestamp' => 'Timestamp',
+ 'TimeStamp' => 'Vremenski pečat',
+ 'Time' => 'Vrijeme',
+ 'Today' => 'Danas',
+ 'Tools' => 'Alati',
+ 'Total' => 'Ukupno',
+ 'TotalBrScore' => 'Total Score',
+ 'TrackDelay' => 'Kašnjenje',
+ 'TrackMotion' => 'Prati pokret',
+ 'Triggers' => 'Okidači',
+ 'TurboPanSpeed' => 'Turbo Pan brzina',
+ 'TurboTiltSpeed' => 'Turbo Tilt brzina',
+ 'Type' => 'Tip',
+ 'Unarchive' => 'Dearhiviraj',
+ 'Undefined' => 'Nedefinisano',
+ 'Units' => 'Mjere',
+ 'Unknown' => 'Nepoznato',
+ 'UpdateAvailable' => 'Dostupno je novo ažurranje za Zoneminder .',
+ 'UpdateNotNecessary' => 'Ažuriranje nije potrebno.',
+ 'Update' => 'Ažuiriaj',
+ 'Upload' => 'Upload',
+ 'Updated' => 'Ažurirano',
+ 'UsedPlugins' => 'Korišteni plugini ',
+ 'UseFilterExprsPost' => ' filter expressions', // This is used at the end of the phrase 'use N filter expressions'
+ 'UseFilterExprsPre' => 'Use ', // This is used at the beginning of the phrase 'use N filter expressions'
+ 'UseFilter' => 'Koristi filter',
+ 'Username' => 'Korisničko ime',
+ 'Users' => 'Korisnici',
+ 'User' => 'Korisnik',
+ 'Value' => 'Vrijednost',
+ 'VersionIgnore' => 'Ignoriši ovu verziju',
+ 'VersionRemindDay' => 'Podsjeti me za jedan dan',
+ 'VersionRemindHour' => 'Podsjeti me za jedan sat',
+ 'VersionRemindNever' => 'Ne podsjecaj me na nove verzije',
+ 'VersionRemindWeek' => 'Podsjeti me za sedam dana',
+ 'Version' => 'Verzija',
+ 'VideoFormat' => 'Video Format',
+ 'VideoGenFailed' => 'Generisanje videa nije uspjelo!',
+ 'VideoGenFiles' => 'Postojece video datoteke',
+ 'VideoGenNoFiles' => 'Video datoteke nisu pronadjene',
+ 'VideoGenParms' => 'Parametri za generisanje videa',
+ 'VideoGenSucceeded' => 'Generisanje videa uspjelo!',
+ 'VideoSize' => 'Velicina videa',
+ 'VideoWriter' => 'Video pisac',
+ 'Video' => 'Video',
+ 'ViewAll' => 'Pregledaj sve',
+ 'ViewEvent' => 'Pregled događaja',
+ 'ViewPaged' => 'Stanični pregled',
+ 'View' => 'Pregled',
+ 'V4L' => 'V4L',
+ 'V4LCapturesPerFrame' => 'Snimci po frejmu',
+ 'V4LMultiBuffer' => 'Višestr. bafer',
+ 'Wake' => 'Budi',
+ 'WarmupFrames' => 'Warmup frejmovi',
+ 'Watch' => 'Gledaj',
+ 'WebColour' => 'Web boja',
+ 'Web' => 'Web',
+ 'WebSiteUrl' => 'URL web stranice',
+ 'Week' => 'Sedmica',
+ 'WhiteBalance' => 'Balans bijele',
+ 'White' => 'Bijelo',
+ 'Wide' => 'Široko',
+ 'X10ActivationString' => 'X10 znakovni niz za aktiviranje',
+ 'X10InputAlarmString' => 'X10 ulazni znakovni niz za alarm',
+ 'X10OutputAlarmString' => 'X10 izlazni znakovni niz za alarm',
+ 'X10' => 'X10',
+ 'X' => 'X',
+ 'Yes' => 'Da',
+ 'YouNoPerms' => 'Nemate potrebne dozvole za pristup ovom resursu.',
+ 'Y' => 'Y',
+ 'ZoneAlarmColour' => 'Boja alarma (Red/Green/Blue)',
+ 'ZoneArea' => 'Oblast zone',
+ 'ZoneFilterSize' => 'Filter Width/Height (pixels)',
+ 'ZoneMinderLog' => 'ZoneMinder zapisnik',
+ 'ZoneMinMaxAlarmArea' => 'Min/Max alarmirana oblast',
+ 'ZoneMinMaxBlobArea' => 'Min/Max blob oblast',
+ 'ZoneMinMaxBlobs' => 'Min/Max Blobovi',
+ 'ZoneMinMaxFiltArea' => 'Min/Max filtrirane oblasti',
+ 'ZoneMinMaxPixelThres' => 'Min/Max Pixel Threshold (0-255)',
+ 'ZoneOverloadFrames' => 'Overload Frame Ignore Count',
+ 'ZoneExtendAlarmFrames' => 'Extend Alarm Frame Count',
+ 'Zones' => 'Zone',
+ 'Zone' => 'Zona',
+ 'ZoomIn' => 'Zoom In',
+ 'ZoomOut' => 'Zoom Out',
+ 'Zoom' => 'Zumiranje',
+);
+
+// Complex replacements with formatting and/or placements, must be passed through sprintf
+$CLANG = array(
+ 'CurrentLogin' => 'Prijavljeni ste kao \'%1$s\'',
+ 'EventCount' => '%1$s %2$s', // For example '37 Events' (from Vlang below)
+ 'LastEvents' => 'Last %1$s %2$s', // For example 'Last 37 Events' (from Vlang below)
+ 'LatestRelease' => 'Zadnja verzija servera je v%1$s, vi imate v%2$s.',
+ 'MonitorCount' => '%1$s %2$s', // For example '4 Monitors' (from Vlang below)
+ 'MonitorFunction' => 'Monitor %1$s Function',
+ 'RunningRecentVer' => 'Koristite najnoviju verziju Zoneminder servera, v%s.',
+ 'VersionMismatch' => 'Version mismatch, system is version %1$s, database is %2$s.',
+);
+
+// The next section allows you to describe a series of word ending and counts used to
+// generate the correctly conjugated forms of words depending on a count that is associated
+// with that word.
+// This intended to allow phrases such a '0 potatoes', '1 potato', '2 potatoes' etc to
+// conjugate correctly with the associated count.
+// In some languages such as English this is fairly simple and can be expressed by assigning
+// a count with a singular or plural form of a word and then finding the nearest (lower) value.
+// So '0' of something generally ends in 's', 1 of something is singular and has no extra
+// ending and 2 or more is a plural and ends in 's' also. So to find the ending for '187' of
+// something you would find the nearest lower count (2) and use that ending.
+//
+// So examples of this would be
+// $zmVlangPotato = array( 0=>'Potatoes', 1=>'Potato', 2=>'Potatoes' );
+// $zmVlangSheep = array( 0=>'Sheep' );
+//
+// where you can have as few or as many entries in the array as necessary
+// If your language is similar in form to this then use the same format and choose the
+// appropriate zmVlang function below.
+// If however you have a language with a different format of plural endings then another
+// approach is required . For instance in Russian the word endings change continuously
+// depending on the last digit (or digits) of the numerator. In this case then zmVlang
+// arrays could be written so that the array index just represents an arbitrary 'type'
+// and the zmVlang function does the calculation about which version is appropriate.
+//
+// So an example in Russian might be (using English words, and made up endings as I
+// don't know any Russian!!)
+// 'Potato' => array( 1=>'Potati', 2=>'Potaton', 3=>'Potaten' ),
+//
+// and the zmVlang function decides that the first form is used for counts ending in
+// 0, 5-9 or 11-19 and the second form when ending in 1 etc.
+//
+
+// Variable arrays expressing plurality, see the zmVlang description above
+$VLANG = array(
+ 'Event' => array( 0=>'Events', 1=>'Event', 2=>'Events' ),
+ 'Monitor' => array( 0=>'Monitors', 1=>'Monitor', 2=>'Monitors' ),
+);
+// You will need to choose or write a function that can correlate the plurality string arrays
+// with variable counts. This is used to conjugate the Vlang arrays above with a number passed
+// in to generate the correct noun form.
+//
+// In languages such as English this is fairly simple
+// Note this still has to be used with printf etc to get the right formatting
+function zmVlang( $langVarArray, $count )
+{
+ krsort( $langVarArray );
+ foreach ( $langVarArray as $key=>$value )
+ {
+ if ( abs($count) >= $key )
+ {
+ return( $value );
+ }
+ }
+ die( 'Error, unable to correlate variable language string' );
+}
+
+// This is an version that could be used in the Russian example above
+// The rules are that the first word form is used if the count ends in
+// 0, 5-9 or 11-19. The second form is used then the count ends in 1
+// (not including 11 as above) and the third form is used when the
+// count ends in 2-4, again excluding any values ending in 12-14.
+//
+// function zmVlang( $langVarArray, $count )
+// {
+// $secondlastdigit = substr( $count, -2, 1 );
+// $lastdigit = substr( $count, -1, 1 );
+// // or
+// // $secondlastdigit = ($count/10)%10;
+// // $lastdigit = $count%10;
+//
+// // Get rid of the special cases first, the teens
+// if ( $secondlastdigit == 1 && $lastdigit != 0 )
+// {
+// return( $langVarArray[1] );
+// }
+// switch ( $lastdigit )
+// {
+// case 0 :
+// case 5 :
+// case 6 :
+// case 7 :
+// case 8 :
+// case 9 :
+// {
+// return( $langVarArray[1] );
+// break;
+// }
+// case 1 :
+// {
+// return( $langVarArray[2] );
+// break;
+// }
+// case 2 :
+// case 3 :
+// case 4 :
+// {
+// return( $langVarArray[3] );
+// break;
+// }
+// }
+// die( 'Error, unable to correlate variable language string' );
+// }
+
+// This is an example of how the function is used in the code which you can uncomment and
+// use to test your custom function.
+//$monitors = array();
+//$monitors[] = 1; // Choose any number
+//echo sprintf( $CLANG['MonitorCount'], count($monitors), zmVlang( $VLANG['VlangMonitor'], count($monitors) ) );
+
+// In this section you can override the default prompt and help texts for the options area
+// These overrides are in the form show below where the array key represents the option name minus the initial ZM_
+// So for example, to override the help text for ZM_LANG_DEFAULT do
+$OLANG = array(
+ 'OPTIONS_FFMPEG' => array(
+ 'Help' => "Parameters in this field are passed on to FFmpeg. Multiple parameters can be separated by ,~~ ".
+ "Examples (do not enter quotes)~~~~".
+ "\"allowed_media_types=video\" Set datatype to request fromcam (audio, video, data)~~~~".
+ "\"reorder_queue_size=nnn\" Set number of packets to buffer for handling of reordered packets~~~~".
+ "\"loglevel=debug\" Set verbosity of FFmpeg (quiet, panic, fatal, error, warning, info, verbose, debug)"
+ ),
+ 'OPTIONS_RTSPTrans' => array(
+ 'Help' => "This sets the RTSP Transport Protocol for FFmpeg.~~ ".
+ "TCP - Use TCP (interleaving within the RTSP control channel) as transport protocol.~~".
+ "UDP - Use UDP as transport protocol. Higher resolution cameras have experienced some 'smearing' while using UDP, if so try TCP~~".
+ "UDP Multicast - Use UDP Multicast as transport protocol~~".
+ "HTTP - Use HTTP tunneling as transport protocol, which is useful for passing proxies.~~"
+ ),
+ 'OPTIONS_LIBVLC' => array(
+ 'Help' => "Parameters in this field are passed on to libVLC. Multiple parameters can be separated by ,~~ ".
+ "Examples (do not enter quotes)~~~~".
+ "\"--rtp-client-port=nnn\" Set local port to use for rtp data~~~~".
+ "\"--verbose=2\" Set verbosity of libVLC"
+ ),
+ 'OPTIONS_EXIF' => array(
+ 'Help' => "Enable this option to embed EXIF data into each jpeg frame."
+ ),
+ 'OPTIONS_RTSPDESCRIBE' => array(
+ 'Help' => "Sometimes, during the initial RTSP handshake, the camera will send an updated media URL. ".
+ "Enable this option to tell ZoneMinder to use this URL. Disable this option to ignore the ".
+ "value from the camera and use the value as entered in the monitor configuration~~~~".
+ "Generally this should be enabled. However, there are cases where the camera can get its".
+ "own URL incorrect, such as when the camera is streaming through a firewall"),
+ 'OPTIONS_MAXFPS' => array(
+ 'Help' => "This field has certain limitations when used for non-local devices.~~ ".
+ "Failure to adhere to these limitations will cause a delay in live video, irregular frame skipping, ".
+ "and missed events~~".
+ "For streaming IP cameras, do not use this field to reduce the frame rate. Set the frame rate in the".
+ " camera, instead. You can, however, use a value that is slightly higher than the frame rate in the camera. ".
+ "In this case, this helps keep the cpu from being overtaxed in the event of a network problem.~~".
+ "Some, mostly older, IP cameras support snapshot mode. In this case ZoneMinder is actively polling the camera ".
+ "for new images. In this case, it is safe to use the field."
+ ),
+
+// 'LANG_DEFAULT' => array(
+// 'Prompt' => "This is a new prompt for this option",
+// 'Help' => "This is some new help for this option which will be displayed in the popup window when the ? is clicked"
+// ),
+);
+
+?>
From 349693e27de728eb20270f7b405c6a6b5c58de23 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 25 Oct 2018 11:24:23 -0400
Subject: [PATCH 038/240] Add a missing comma
---
scripts/zmfilter.pl.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in
index f9029016a..3f7e720c3 100644
--- a/scripts/zmfilter.pl.in
+++ b/scripts/zmfilter.pl.in
@@ -576,7 +576,8 @@ sub uploadArchFile {
$host .= ':'.$Config{ZM_UPLOAD_PORT} if $Config{ZM_UPLOAD_PORT};
Info('Uploading to '.$host.' using SFTP');
my %sftpOptions = (
- host=>$Config{ZM_UPLOAD_HOST}, user=>$Config{ZM_UPLOAD_USER}
+ host=>$Config{ZM_UPLOAD_HOST},
+ user=>$Config{ZM_UPLOAD_USER},
($Config{ZM_UPLOAD_PASS} ? (password=>$Config{ZM_UPLOAD_PASS}) : ()),
($Config{ZM_UPLOAD_PORT} ? (port=>$Config{ZM_UPLOAD_PORT}) : ()),
($Config{ZM_UPLOAD_TIMEOUT} ? (timeout=>$Config{ZM_UPLOAD_TIMEOUT}) : ()),
From 91d83a89fa1909d27ad248e901151584823c877b Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 25 Oct 2018 15:40:12 -0400
Subject: [PATCH 039/240] include semaphore function replacements
---
web/includes/functions.php | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/web/includes/functions.php b/web/includes/functions.php
index 0f49f611c..76117ad5a 100644
--- a/web/includes/functions.php
+++ b/web/includes/functions.php
@@ -2273,4 +2273,30 @@ function unparse_url($parsed_url, $substitutions = array() ) {
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
return "$scheme$user$pass$host$port$path$query$fragment";
}
+
+// The following works around php not being built with semaphore functions.
+if (!function_exists('sem_get')) {
+ function sem_get($key) {
+ return fopen(__FILE__ . '.sem.' . $key, 'w+');
+ }
+ function sem_acquire($sem_id) {
+ return flock($sem_id, LOCK_EX);
+ }
+ function sem_release($sem_id) {
+ return flock($sem_id, LOCK_UN);
+ }
+}
+
+if( !function_exists('ftok') ) {
+ function ftok($filename = "", $proj = "") {
+ if ( empty($filename) || !file_exists($filename) ) {
+ return -1;
+ } else {
+ $filename = $filename . (string) $proj;
+ for($key = array(); sizeof($key) < strlen($filename); $key[] = ord(substr($filename, sizeof($key), 1)));
+ return dechex(array_sum($key));
+ }
+ }
+}
+
?>
From aaeb30a72f12524671ccd07c7ea51b26fc9bc573 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Sun, 28 Oct 2018 17:50:22 -0400
Subject: [PATCH 040/240] Move license down to perldocs at bottom. Remove
unecessary line feeds and spaces
---
scripts/zmstats.pl.in | 77 ++++++++++++++++++++++---------------------
1 file changed, 39 insertions(+), 38 deletions(-)
diff --git a/scripts/zmstats.pl.in b/scripts/zmstats.pl.in
index 25bccfebc..410459158 100644
--- a/scripts/zmstats.pl.in
+++ b/scripts/zmstats.pl.in
@@ -1,39 +1,4 @@
#!/usr/bin/perl -wT
-#
-# ==========================================================================
-#
-# ZoneMinder WatchDog Script, $Date$, $Revision$
-# Copyright (C) 2001-2008 Philip Coombes
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# ==========================================================================
-
-=head1 NAME
-
-zmwatch.pl - ZoneMinder Stats Updating Script
-
-=head1 SYNOPSIS
-
-zmstats.pl
-
-=head1 DESCRIPTION
-
-This does background updating various stats in the db like event counts, diskspace, etc.
-
-=cut
use strict;
use bytes;
@@ -66,8 +31,8 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
logInit();
logSetSignal();
-Info( "Stats Daemon starting in ".START_DELAY." seconds\n" );
-sleep( START_DELAY );
+Info("Stats Daemon starting in ".START_DELAY." seconds");
+sleep(START_DELAY);
my $dbh = zmDbConnect();
@@ -88,7 +53,43 @@ while( 1 ) {
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
} # end while (1)
-Info( "Stats Daemon exiting\n" );
+Info("Stats Daemon exiting");
exit();
1;
__END__
+
+#
+# ==========================================================================
+#
+# ZoneMinder WatchDog Script, $Date$, $Revision$
+# Copyright (C) 2001-2008 Philip Coombes
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# ==========================================================================
+
+=head1 NAME
+
+zmstats.pl - ZoneMinder Stats Updating Script
+
+=head1 SYNOPSIS
+
+zmstats.pl
+
+=head1 DESCRIPTION
+
+This does background updating various stats in the db like event counts, diskspace, etc.
+
+=cut
From 0d1f8aaf03ca01f712206463254a3932eb099ef5 Mon Sep 17 00:00:00 2001
From: Matt N
Date: Sun, 28 Oct 2018 17:15:39 -0700
Subject: [PATCH 041/240] Document /api/monitors/daemonStatus/
---
docs/api.rst | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/docs/api.rst b/docs/api.rst
index a6d0cc9aa..d4d4f3415 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -148,6 +148,13 @@ This API changes monitor 1 to Modect and Enabled
::
curl -XPOST http://server/zm/api/monitors/1.json -d "Monitor[Function]=Modect&Monitor[Enabled]=1"
+
+Get Daemon Status of Monitor 1
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+::
+
+ curl http://server/zm/api/monitors/daemonStatus/id:1/daemon:zmc.json
Add a monitor
^^^^^^^^^^^^^^
From 95a6d0666a55f2e734658b3ee2db9496661bead8 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 29 Oct 2018 09:59:26 -0400
Subject: [PATCH 042/240] Improve behaviour and reduce extra logging when db
goes away
---
web/includes/Event.php | 8 +++---
web/includes/functions.php | 31 ++++++++++++------------
web/skins/classic/includes/functions.php | 2 +-
3 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/web/includes/Event.php b/web/includes/Event.php
index 1852bb8b0..fb7af931e 100644
--- a/web/includes/Event.php
+++ b/web/includes/Event.php
@@ -546,9 +546,11 @@ class Event {
}
$filters = array();
$result = dbQuery($sql, $values);
- $results = $result->fetchALL();
- foreach ( $results as $row ) {
- $filters[] = new Event($row);
+ if ( $result ) {
+ $results = $result->fetchALL();
+ foreach ( $results as $row ) {
+ $filters[] = new Event($row);
+ }
}
return $filters;
}
diff --git a/web/includes/functions.php b/web/includes/functions.php
index 76117ad5a..29f627722 100644
--- a/web/includes/functions.php
+++ b/web/includes/functions.php
@@ -1909,23 +1909,24 @@ function logState() {
# This is an expensive request, as it has to hit every row of the Logs Table
$sql = 'SELECT Level, COUNT(Level) AS LevelCount FROM Logs WHERE Level < '.Logger::INFO.' AND TimeKey > unix_timestamp(now() - interval '.ZM_LOG_CHECK_PERIOD.' second) GROUP BY Level ORDER BY Level ASC';
- $counts = dbFetchAll( $sql );
-
- foreach ( $counts as $count ) {
- if ( $count['Level'] <= Logger::PANIC )
- $count['Level'] = Logger::FATAL;
- if ( !($levelCount = $levelCounts[$count['Level']]) ) {
- Error( "Unexpected Log level ".$count['Level'] );
- next;
- }
- if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) {
- $state = 'alarm';
- break;
- } elseif ( $levelCount[0] && $count['LevelCount'] >= $levelCount[0] ) {
- $state = 'alert';
+ $counts = dbFetchAll($sql);
+ if ( $counts ) {
+ foreach ( $counts as $count ) {
+ if ( $count['Level'] <= Logger::PANIC )
+ $count['Level'] = Logger::FATAL;
+ if ( !($levelCount = $levelCounts[$count['Level']]) ) {
+ Error('Unexpected Log level '.$count['Level']);
+ next;
+ }
+ if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) {
+ $state = 'alarm';
+ break;
+ } elseif ( $levelCount[0] && $count['LevelCount'] >= $levelCount[0] ) {
+ $state = 'alert';
+ }
}
}
- return( $state );
+ return $state;
}
function isVector ( &$array ) {
diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php
index ceb12d621..7847e37c7 100644
--- a/web/skins/classic/includes/functions.php
+++ b/web/skins/classic/includes/functions.php
@@ -345,7 +345,7 @@ if ($reload == 'reload') ob_start();
90 ? ' class="warning"' : '' ).'>'.translate('DB').':'.$connections.'/'.$max_connections.'';
?>
:
From 9a2d58adceaa6b1335e48290dda64770812033f7 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 29 Oct 2018 11:03:03 -0400
Subject: [PATCH 043/240] We don't store all the permissions in the session
anymore. We just use the global user object
---
web/api/app/Controller/MonitorsController.php | 6 ++++--
web/api/app/Controller/StatesController.php | 5 +++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php
index 5ce4bb476..185a06c84 100644
--- a/web/api/app/Controller/MonitorsController.php
+++ b/web/api/app/Controller/MonitorsController.php
@@ -207,8 +207,10 @@ class MonitorsController extends AppController {
if ( !$this->Monitor->exists() ) {
throw new NotFoundException(__('Invalid monitor'));
}
- if ( $this->Session->Read('systemPermission') != 'Edit' ) {
- throw new UnauthorizedException(__('Insufficient privileges'));
+ global $user;
+ $canEdit = (!$user) || ($user['System'] == 'Edit');
+ if ( !$canEdit ) {
+ throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
$this->request->allowMethod('post', 'delete');
diff --git a/web/api/app/Controller/StatesController.php b/web/api/app/Controller/StatesController.php
index 29201d2c1..b96efe0aa 100644
--- a/web/api/app/Controller/StatesController.php
+++ b/web/api/app/Controller/StatesController.php
@@ -59,8 +59,9 @@ public function add() {
if ($this->request->is('post')) {
- if ($this->Session->Read('systemPermission') != 'Edit')
- {
+ global $user;
+ $canEdit = (!$user) || ($user['System'] == 'Edit');
+ if ( !$canEdit ) {
throw new UnauthorizedException(__('Insufficient privileges'));
return;
}
From 6691b5fb52b09f4dfcedd4b7bac47d421c991b1e Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 29 Oct 2018 12:50:50 -0400
Subject: [PATCH 044/240] Include CORS headers when there is a Server defined,
instead of requiring there to be more than 1
---
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 29f627722..7fe174470 100644
--- a/web/includes/functions.php
+++ b/web/includes/functions.php
@@ -41,7 +41,7 @@ function CORSHeaders() {
# The following is left for future reference/use.
$valid = false;
$Servers = Server::find();
- if ( sizeof($Servers) <= 1 ) {
+ if ( sizeof($Servers) < 1 ) {
# Only need CORSHeaders in the event that there are multiple servers in use.
# ICON: Might not be true. multi-port?
return;
From 39061038fb331369c12e984a08011a9fc7933a67 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 29 Oct 2018 14:40:05 -0400
Subject: [PATCH 045/240] Don't include related models in Storage index
---
web/api/app/Controller/StorageController.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/api/app/Controller/StorageController.php b/web/api/app/Controller/StorageController.php
index 325dea4dd..16791788c 100644
--- a/web/api/app/Controller/StorageController.php
+++ b/web/api/app/Controller/StorageController.php
@@ -31,7 +31,7 @@ class StorageController extends AppController {
* @return void
*/
public function index() {
- $this->Storage->recursive = 0;
+ $this->Storage->recursive = -1;
$options = '';
$storage_areas = $this->Storage->find('all',$options);
From f95379742b325bfc5d9d8c28df46068a7b8400f3 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Tue, 30 Oct 2018 12:04:05 -0400
Subject: [PATCH 046/240] Use a warning colour when motion detection is
disabled.
---
web/skins/classic/css/base/skin.css | 12 ++++++------
web/skins/classic/views/console.php | 20 ++++++++++++--------
2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/web/skins/classic/css/base/skin.css b/web/skins/classic/css/base/skin.css
index 3fdd5a12f..f95c0003e 100644
--- a/web/skins/classic/css/base/skin.css
+++ b/web/skins/classic/css/base/skin.css
@@ -341,17 +341,17 @@ fieldset > legend {
/*
* Behavior classes
*/
-.alarm, .errorText, .error {
- color: #ff3f34;
-}
-.alert, .warnText, .warning {
- color: #ffa801;
-}
.ok, .infoText {
color: #0fb9b1;
}
+.alert, .warnText, .warning, .disabledText {
+ color: #ffa801;
+}
+.alarm, .errorText, .error {
+ color: #ff3f34;
+}
.fakelink {
color: #7f7fb2;
diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php
index 46575ffa0..6de978a6c 100644
--- a/web/skins/classic/views/console.php
+++ b/web/skins/classic/views/console.php
@@ -251,15 +251,19 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
}
}
if ( $monitor['Function'] == 'None' )
- $fclass = 'errorText';
+ $function_class = 'errorText';
else
- $fclass = 'infoText';
- if ( !$monitor['Enabled'] )
- $fclass .= ' disabledText';
+ $function_class = 'infoText';
+
+
$scale = max(reScale(SCALE_BASE, $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE), SCALE_BASE);
$stream_available = canView('Stream') and $monitor['Type']=='WebSite' or ($monitor['CaptureFPS'] && $monitor['Function'] != 'None');
- $dot_class=$source_class;
- if ( $fclass != 'infoText' ) $dot_class=$fclass;
+ $dot_class = $source_class;
+ if ( $function_class != 'infoText' ) {
+ $dot_class = $function_class;
+ } else if ( !$monitor['Enabled'] ) {
+ $dot_class .= ' warnText';
+ }
if ( ZM_WEB_ID_ON_CONSOLE ) {
?>
@@ -268,7 +272,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
}
?>
Date: Tue, 30 Oct 2018 18:35:50 -0400
Subject: [PATCH 047/240] Fixes for a couple issues in the Ubuntu guide (#2285)
* Xenial needs the ppa:iconnor/zoneminder repo
Otherwise, trying to install the zoneminder package fails with an unmet
dependency on php-apc.
See https://forums.zoneminder.com/viewtopic.php?t=27638 for details.
* Add necessary modules before configuring Apache
When you add the zoneminder configuration before enabling mod_rewrite,
subsequent commands (like the one to enable mod_cgi) give you an error
like:
AH00526: Syntax error on line 37 of /etc/apache2/conf-enabled/zoneminder.conf:
Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration
---
docs/installationguide/ubuntu.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/installationguide/ubuntu.rst b/docs/installationguide/ubuntu.rst
index 3df065264..6c686d7ed 100644
--- a/docs/installationguide/ubuntu.rst
+++ b/docs/installationguide/ubuntu.rst
@@ -49,7 +49,7 @@ guide you with a quick search.
add-apt-repository ppa:iconnor/zoneminder-1.32
- If you are on trusty, you may want to add both, as there are some packages for dependencies included in the old ppa.
+ If you are on Trusty or Xenial, you may want to add both, as there are some packages for dependencies included in the old ppa.
Update repo and upgrade.
@@ -138,9 +138,9 @@ Set /etc/zm/zm.conf to root:www-data 740 and www-data access to content
::
- a2enconf zoneminder
a2enmod cgi
a2enmod rewrite
+ a2enconf zoneminder
You may also want to enable to following modules to improve caching performance
From 2b0df3e4e2c9b064088a02eac6d5ce190e9d0561 Mon Sep 17 00:00:00 2001
From: ratmole
Date: Wed, 31 Oct 2018 10:17:36 +0200
Subject: [PATCH 048/240] API - Disable E_NOTICE from php error reporting in
cake debug
Using zmNinja, the API reports E_NOTICE errors
Notice (8): compact(): Undefined variable: subject [CORE/Cake/Utility/ObjectCollection.php, line 128]
Notice (8): compact() [function.compact]: Undefined variable: subject [CORE/Cake/Utility/ObjectCollection.php, line 128]
Notice (8): compact() [function.compact]: Undefined variable: subject [CORE/Cake/Utility/ObjectCollection.php, line 128]
Notice (8): compact() [function.compact]: Undefined variable: subject [CORE/Cake/Utility/ObjectCollection.php, line 128]
and zmNinja will not work...
there is a better way, but i think disabling E_NOTICE error is way easier
see: https://github.com/ZoneMinder/zoneminder/pull/2269
---
web/api/app/Config/core.php.default | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/api/app/Config/core.php.default b/web/api/app/Config/core.php.default
index 39a51690c..64f439420 100644
--- a/web/api/app/Config/core.php.default
+++ b/web/api/app/Config/core.php.default
@@ -50,7 +50,7 @@
*/
Configure::write('Error', array(
'handler' => 'ErrorHandler::handleError',
- 'level' => E_ALL & ~E_DEPRECATED,
+ 'level' => E_ALL & ~E_DEPRECATED & ~E_NOTICE,
'trace' => true
));
From e87ded35f1b7f530abb013bcf351431ad4a03a92 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 31 Oct 2018 11:08:44 -0400
Subject: [PATCH 049/240] rough in adding Monitor_Status to Monitors
---
web/api/app/Model/Monitor.php | 9 ++++-
web/api/app/Model/Monitor_Status.php | 59 ++++++++++++++++++++++++++++
2 files changed, 67 insertions(+), 1 deletion(-)
create mode 100644 web/api/app/Model/Monitor_Status.php
diff --git a/web/api/app/Model/Monitor.php b/web/api/app/Model/Monitor.php
index 5c0f62641..2e6584794 100644
--- a/web/api/app/Model/Monitor.php
+++ b/web/api/app/Model/Monitor.php
@@ -116,8 +116,15 @@ class Monitor extends AppModel {
'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'),
'OutputContainer' => array('auto','mp4','mkv'),
'DefaultView' => array('Events','Control'),
- 'Status' => array('Unknown','NotRunning','Running','NoSignal','Signal'),
+ #'Status' => array('Unknown','NotRunning','Running','NoSignal','Signal'),
)
);
+ public $hasOne = array(
+ 'Monitor_Status' => array(
+ 'className' => 'Monitor_Status',
+ 'foreignKey' => 'MonitorId',
+ 'joinTable' => 'Monitor_Status',
+ )
+ );
}
diff --git a/web/api/app/Model/Monitor_Status.php b/web/api/app/Model/Monitor_Status.php
new file mode 100644
index 000000000..40f4aa2c2
--- /dev/null
+++ b/web/api/app/Model/Monitor_Status.php
@@ -0,0 +1,59 @@
+ array(
+ 'numeric' => array(
+ 'rule' => array('numeric'),
+ //'message' => 'Your custom message here',
+ //'allowEmpty' => false,
+ //'required' => false,
+ //'last' => false, // Stop validation after this rule
+ //'on' => 'create', // Limit validation to 'create' or 'update' operations
+ ),
+ ),
+ );
+
+ public $actsAs = array(
+ 'CakePHP-Enum-Behavior.Enum' => array(
+ 'Status' => array('Unknown','NotRunning','Running','NoSignal','Signal'),
+ )
+ );
+
+ //The Associations below have been created with all possible keys, those that are not needed can be removed
+}
From 69f7d367296d16e11f3d6833bdbb6cca84444704 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 31 Oct 2018 11:34:30 -0400
Subject: [PATCH 050/240] Make it clear that audio recording is only for ffmpeg
input type
---
web/skins/classic/views/monitor.php | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php
index fa2ebd44f..979d4f34e 100644
--- a/web/skins/classic/views/monitor.php
+++ b/web/skins/classic/views/monitor.php
@@ -937,7 +937,15 @@ if ( $monitor->Type() == 'Local' ) {
?>
-
RecordAudio() ) { ?> checked="checked"/>
+
+Type() == 'Ffmpeg' ) { ?>
+ RecordAudio() ) { ?> checked="checked"/>
+
+ Audio recording only available with FFMPEG
+
+
+
+
Date: Wed, 31 Oct 2018 11:35:06 -0400
Subject: [PATCH 051/240] add further note about needing h264 passthrough
---
web/skins/classic/views/monitor.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php
index 979d4f34e..5142e4a96 100644
--- a/web/skins/classic/views/monitor.php
+++ b/web/skins/classic/views/monitor.php
@@ -941,7 +941,7 @@ if ( $monitor->Type() == 'Local' ) {
Type() == 'Ffmpeg' ) { ?>
RecordAudio() ) { ?> checked="checked"/>
- Audio recording only available with FFMPEG
+ Audio recording only available with FFMPEG using H264 Passthrough
From bdb50567df2787e52bca8bbb5f306a71c6871263 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 31 Oct 2018 11:56:08 -0400
Subject: [PATCH 052/240] fix disk_event_space to event_disk_space
---
web/includes/Storage.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/includes/Storage.php b/web/includes/Storage.php
index 0744889f9..95f1dab84 100644
--- a/web/includes/Storage.php
+++ b/web/includes/Storage.php
@@ -189,7 +189,7 @@ class Storage {
# This isn't a function like this in php, so we have to add up the space used in each event.
if ( ( !array_key_exists('disk_used_space', $this)) or !$this->{'disk_used_space'} ) {
if ( $this->{'Type'} == 's3fs' ) {
- $this->{'disk_used_space'} = $this->disk_event_space();
+ $this->{'disk_used_space'} = $this->event_disk_space();
} else {
$path = $this->Path();
if ( file_exists($path) ) {
From 37b2da59ce7047b1d6d57bd1e63a6f4824e24232 Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 13:30:08 -0400
Subject: [PATCH 053/240] added streaming interface docs
---
docs/api.rst | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)
diff --git a/docs/api.rst b/docs/api.rst
index d4d4f3415..109569492 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -5,7 +5,6 @@ This document will provide an overview of ZoneMinder's API. This is work in prog
Overview
^^^^^^^^
-
In an effort to further 'open up' ZoneMinder, an API was needed. This will
allow quick integration with and development of ZoneMinder.
@@ -13,6 +12,78 @@ The API is built in CakePHP and lives under the ``/api`` directory. It
provides a RESTful service and supports CRUD (create, retrieve, update, delete)
functions for Monitors, Events, Frames, Zones and Config.
+Streaming Interface
+^^^^^^^^^^^^^^^^^^^
+Developers working on their application often ask if there is an "API" to receive live streams, or recorded event streams.
+It is possible to stream both live and recorded streams. This isn't strictly an "API" per-se (that is, it is not integrated
+into the Cake PHP based API layer discussed here) and also why we've used the term "Interface" instead of an "API".
+
+Live Streams
+=============
+What you need to know is that if you want to display "live streams", ZoneMinder sends you streaming JPEG images (MJPEG)
+which can easily be rendered in a browser using an ``img src`` tag.
+
+For example:
+
+::
+
+
+
+will display a live feed from monitor id 1, scaled down by 50% in quality and resized to 640x480px.
+
+* This assumes ``/zm/cgi-bin`` is your CGI_BIN path. Change it to what is correct in your system
+* The "auth" token you see above is required if you use ZoneMinder authentication. To understand how to get the auth token, please read the "Login, Logout & API security" section below.
+* The "connkey" parameter is essentially a random number which uniquely identifies a stream. If you don't specify a connkey, ZM will generate its own. It is recommended to generate a connkey because you can then use it to "control" the stream (pause/resume etc.)
+* Instead of dealing with the "auth" token, you can also use ``&user=username&pass=password`` where "username" and "password" are your ZoneMinder username and password respectively. Note that this is not recommended because you are transmitting them in a URL and even if you use HTTPS, they may show up in web server logs.
+
+
+PTZ on live streams
+-------------------
+PTZ commands are pretty cryptic in ZoneMinder. This is not meant to be an exhaustive guide, but just something to whet your appetite:
+
+
+Lets assume you have a monitor, with ID=6. Let's further assume you want to pan it left.
+
+You'd need to send a:
+``POST`` command to ``https://yourserver/zm/index.php`` with the following data payload in the command (NOT in the URL)
+
+``view=request&request=control&id=6&control=moveConLeft&xge=30&yge=30``
+
+Obviously, if you are using authentication, you need to be logged in for this to work.
+
+Like I said, at this stage, this is only meant to get you started. Explore the ZoneMinder code and use "Inspect source" as you use PTZ commands in the ZoneMinder source code.
+`control_functions.php `__ is a great place to start.
+
+
+Pre-recorded (past event) streams
+=================================
+
+Similar to live playback, if you have chosen to store events in JPEG mode, you can play it back using:
+
+::
+
+
+
+
+* This assumes ``/zm/cgi-bin`` is your CGI_BIN path. Change it to what is correct in your system
+* This will playback event 293820, starting from frame 1 as an MJPEG stream
+* Like before, you can add more parameters like ``scale`` etc.
+* auth and connkey have the same meaning as before, and yes, you can replace auth by ``&user=usename&pass=password`` as before and the same security concerns cited above apply.
+
+If instead, you have chosen to use the MP4 (Video) storage mode for events, you can directly play back the saved video file:
+
+::
+
+
+
+* This will play back the video recording for event 294690
+
+What other parameters are supported?
+=====================================
+The best way to answer this question is to play with ZoneMinder console. Open a browser, play back live or recorded feed, and do an "Inspect Source" to see what parameters
+are generated. Change and observe.
+
+
Enabling API
^^^^^^^^^^^^
A default ZoneMinder installs with APIs enabled. You can explictly enable/disable the APIs
@@ -396,6 +467,8 @@ PTZ Control APIs
PTZ controls associated with a monitor are stored in the Controls table and not the Monitors table inside ZM. What that means is when you get the details of a Monitor, you will only know if it is controllable (isControllable:true) and the control ID.
To be able to retrieve PTZ information related to that Control ID, you need to use the controls API
+Note that these APIs only retrieve control data related to PTZ. They don't actually move the camera.
+
This returns all the control definitions:
::
From 2953ff4db4afa15266917d9deffe28375108811e Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 13:40:07 -0400
Subject: [PATCH 054/240] header level fix
---
docs/api.rst | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/docs/api.rst b/docs/api.rst
index 109569492..a06797cd1 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -19,7 +19,7 @@ It is possible to stream both live and recorded streams. This isn't strictly an
into the Cake PHP based API layer discussed here) and also why we've used the term "Interface" instead of an "API".
Live Streams
-=============
+~~~~~~~~~~~~~~
What you need to know is that if you want to display "live streams", ZoneMinder sends you streaming JPEG images (MJPEG)
which can easily be rendered in a browser using an ``img src`` tag.
@@ -56,7 +56,7 @@ Like I said, at this stage, this is only meant to get you started. Explore the Z
Pre-recorded (past event) streams
-=================================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to live playback, if you have chosen to store events in JPEG mode, you can play it back using:
@@ -79,7 +79,7 @@ If instead, you have chosen to use the MP4 (Video) storage mode for events, you
* This will play back the video recording for event 294690
What other parameters are supported?
-=====================================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The best way to answer this question is to play with ZoneMinder console. Open a browser, play back live or recorded feed, and do an "Inspect Source" to see what parameters
are generated. Change and observe.
@@ -490,3 +490,4 @@ ZM APIs have various APIs that help you in determining host (aka ZM) daemon stat
curl -XGET http://server/zm/api/host/getLoad.json # returns current load of ZM
curl -XGET http://server/zm/api/host/getDiskPercent.json # returns in GB (not percentage), disk usage per monitor (that is, space taken to store various event related information,images etc. per monitor)
+
From cd8d609e846eafa87b86e42fb59a4edf2ba1339c Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 14:00:09 -0400
Subject: [PATCH 055/240] initial multi-server/storage changes
---
docs/api.rst | 101 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 98 insertions(+), 3 deletions(-)
diff --git a/docs/api.rst b/docs/api.rst
index a06797cd1..d70c7eabc 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -142,7 +142,21 @@ using CuRL like so:
curl -b cookies.txt http://yourzmip/zm/api/monitors.json
-This would return a list of monitors and pass on the authentication information to the ZM API layer.
+This would return a list of monitors and pass on the authentication information to the ZM API layer. It is worthwhile noting, that starting ZM 1.32.3 and beyond, this API also returns a ``Monitor_Status`` object per monitor. It looks like this:
+
+::
+
+ "Monitor_Status": {
+ "MonitorId": "2",
+ "Status": "Connected",
+ "CaptureFPS": "1.67",
+ "AnalysisFPS": "1.67",
+ "CaptureBandwidth": "52095"
+ }
+
+
+If you don't see this in your API, you are running an older version of ZM. This gives you a very convenient way to check monitor status without calling the ``daemonCheck`` API described later.
+
A deeper dive into the login process
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -486,8 +500,89 @@ ZM APIs have various APIs that help you in determining host (aka ZM) daemon stat
::
- curl -XGET http://server/zm/api/host/daemonCheck.json # 1 = ZM running 0=not running
curl -XGET http://server/zm/api/host/getLoad.json # returns current load of ZM
- curl -XGET http://server/zm/api/host/getDiskPercent.json # returns in GB (not percentage), disk usage per monitor (that is, space taken to store various event related information,images etc. per monitor)
+
+ # Note that ZM 1.32.3 onwards has the same information in Monitors.json which is more reliable and works for multi-server too.
+ curl -XGET http://server/zm/api/host/daemonCheck.json # 1 = ZM running 0=not running
+
+ # The API below uses "du" to calculate disk space. We no longer recommend you use it if you have many events. Use the Storage APIs instead, described later
+ curl -XGET http://server/zm/api/host/getDiskPercent.json # returns in GB (not percentage), disk usage per monitor (that is,space taken to store various event related information,images etc. per monitor)
+
+
+Storage and Server APIs
+^^^^^^^^^^^^^^^^^^^^^^^
+
+ZoneMinder introduced many new options that allowed you to configure multiserver/multistorage configurations. While a part of this was available in previous versions, a lot of rework was done as part of ZM 1.31 and 1.32. As part of that work, a lot of new and useful APIs were added. Some of these are part of ZM 1.32 and others will be part of ZM 1.32.3 (of course, if you build from master, you can access them right away, or wait till a stable release is out.
+
+
+
+This returns storage data for my single server install. If you are using multi-storage, you'll see many such "Storage" entries, one for each storage defined:
+
+::
+
+ curl http://server/zm/api/storage.json
+
+Returns:
+
+::
+
+ {
+ "storage": [
+ {
+ "Storage": {
+ "Id": "0",
+ "Path": "\/var\/cache\/zoneminder\/events",
+ "Name": "Default",
+ "Type": "local",
+ "Url": null,
+ "DiskSpace": "364705447651",
+ "Scheme": "Medium",
+ "ServerId": null,
+ "DoDelete": true
+ }
+ }
+ ]
+ }
+
+
+
+"DiskSpace" is the disk used in bytes. While this doesn't return disk space data as rich as ``/host/getDiskPercent``, it is much more efficient.
+
+Similarly,
+
+::
+ curl http://server/zm/api/server.json
+
+Returns:
+
+::
+
+ {
+ "servers": [
+ {
+ "Server": {
+ "Id": "1",
+ "Name": "server1",
+ "Hostname": "sserver1.mydomain.com",
+ "State_Id": null,
+ "Status": "Running",
+ "CpuLoad": "0.9",
+ "TotalMem": "6186237952",
+ "FreeMem": "156102656",
+ "TotalSwap": "536866816",
+ "FreeSwap": "525697024",
+ "zmstats": false,
+ "zmaudit": false,
+ "zmtrigger": false
+ }
+ }
+ ]
+ }
+
+This only works if you have a multiserver setup in place. If you don't it will return an empty array.
+
+
+
+
From 46cd2fc3ffb387762c8fa378cee96d117ea07ce6 Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 14:04:51 -0400
Subject: [PATCH 056/240] relocate monitor_status to the right place
---
docs/api.rst | 33 ++++++++++++++++++---------------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/docs/api.rst b/docs/api.rst
index d70c7eabc..ec4fe8d55 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -142,21 +142,7 @@ using CuRL like so:
curl -b cookies.txt http://yourzmip/zm/api/monitors.json
-This would return a list of monitors and pass on the authentication information to the ZM API layer. It is worthwhile noting, that starting ZM 1.32.3 and beyond, this API also returns a ``Monitor_Status`` object per monitor. It looks like this:
-
-::
-
- "Monitor_Status": {
- "MonitorId": "2",
- "Status": "Connected",
- "CaptureFPS": "1.67",
- "AnalysisFPS": "1.67",
- "CaptureBandwidth": "52095"
- }
-
-
-If you don't see this in your API, you are running an older version of ZM. This gives you a very convenient way to check monitor status without calling the ``daemonCheck`` API described later.
-
+This would return a list of monitors and pass on the authentication information to the ZM API layer.
A deeper dive into the login process
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -217,6 +203,22 @@ Return a list of all monitors
curl http://server/zm/api/monitors.json
+It is worthwhile to note that starting ZM 1.32.3 and beyond, this API also returns a ``Monitor_Status`` object per monitor. It looks like this:
+
+::
+
+ "Monitor_Status": {
+ "MonitorId": "2",
+ "Status": "Connected",
+ "CaptureFPS": "1.67",
+ "AnalysisFPS": "1.67",
+ "CaptureBandwidth": "52095"
+ }
+
+
+If you don't see this in your API, you are running an older version of ZM. This gives you a very convenient way to check monitor status without calling the ``daemonCheck`` API described later.
+
+
Retrieve monitor 1
^^^^^^^^^^^^^^^^^^^
@@ -551,6 +553,7 @@ Returns:
Similarly,
::
+
curl http://server/zm/api/server.json
Returns:
From 536d9226e0575ecc34a6f324cd2180b69d823fd8 Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 14:07:53 -0400
Subject: [PATCH 057/240] ptz - clarify this is meta-data
---
docs/api.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/api.rst b/docs/api.rst
index ec4fe8d55..647eedac0 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -478,12 +478,12 @@ Create a Zone
&Zone[MaxBlobs]=\
&Zone[OverloadFrames]=0"
-PTZ Control APIs
-^^^^^^^^^^^^^^^^
+PTZ Control Meta-Data APIs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
PTZ controls associated with a monitor are stored in the Controls table and not the Monitors table inside ZM. What that means is when you get the details of a Monitor, you will only know if it is controllable (isControllable:true) and the control ID.
To be able to retrieve PTZ information related to that Control ID, you need to use the controls API
-Note that these APIs only retrieve control data related to PTZ. They don't actually move the camera.
+Note that these APIs only retrieve control data related to PTZ. They don't actually move the camera. See the "PTZ on live streams" section to move the camera.
This returns all the control definitions:
::
From 14c30eac7682debb92dcc9633755d91bb61dba5c Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 14:08:09 -0400
Subject: [PATCH 058/240] typo
---
docs/api.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/api.rst b/docs/api.rst
index 647eedac0..e102851a7 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -566,7 +566,7 @@ Returns:
"Server": {
"Id": "1",
"Name": "server1",
- "Hostname": "sserver1.mydomain.com",
+ "Hostname": "server1.mydomain.com",
"State_Id": null,
"Status": "Running",
"CpuLoad": "0.9",
From 86a086c216647dc37b503a47be61cb97ea26a794 Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 14:13:22 -0400
Subject: [PATCH 059/240] server json api typo
---
docs/api.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/api.rst b/docs/api.rst
index e102851a7..2c7ad1d16 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -554,7 +554,7 @@ Similarly,
::
- curl http://server/zm/api/server.json
+ curl http://server/zm/api/servers.json
Returns:
From ace1134df137c1bb7bea35156158d57eafe50b0b Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Thu, 1 Nov 2018 14:40:31 -0400
Subject: [PATCH 060/240] further reading
---
docs/api.rst | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/docs/api.rst b/docs/api.rst
index 2c7ad1d16..2f90b7fdf 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -585,7 +585,14 @@ Returns:
This only works if you have a multiserver setup in place. If you don't it will return an empty array.
-
+Further Reading
+^^^^^^^^^^^^^^^^
+As described earlier, treat this document as an "introduction" to the important parts of the API and streaming interfaces.
+There are several details that haven't yet been documented. Till they are, here are some resources:
+
+* zmNinja, the open source mobile app for ZoneMinder is 100% based on ZM APIs. Explore its `source code `__ to see how things work.
+* Launch up ZM console in a browser, and do an "Inspect source". See how images are being rendered. Go to the networks tab of the inspect source console and look at network requests that are made when you pause/play/forward streams.
+* If you still can't find an answer, post your question in the `forums `__ (not the github repo).
From 4b24bf4e36f9b0aa265c89b62dea12c11ec88890 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 2 Nov 2018 11:48:35 -0400
Subject: [PATCH 061/240] merge from storageareas, fully specify Module for
zmDbDisconnect as we havn't 'used' it
---
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 3caa6af4a..6d7ecc660 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm
@@ -705,7 +705,7 @@ sub Fatal( @ ) {
$SIG{TERM}();
}
# I think if we don't disconnect we will leave sockets around in TIME_WAIT
- zmDbDisconnect();
+ ZoneMinder::Database::zmDbDisconnect();
exit(-1);
}
From 3aee902a96daab320f6a1c17c81664d997916d75 Mon Sep 17 00:00:00 2001
From: Andy Bauer
Date: Sun, 4 Nov 2018 17:11:19 -0600
Subject: [PATCH 062/240] update nginx support on redhat
---
distros/redhat/nginx/README.Fedora | 168 +++++++++++-------
distros/redhat/nginx/zoneminder.conf.in | 4 +
.../redhat/nginx/zoneminder.php-fpm.conf.in | 12 +-
distros/redhat/nginx/zoneminder.tmpfiles.in | 3 +
distros/redhat/zoneminder.spec | 3 +-
5 files changed, 118 insertions(+), 72 deletions(-)
diff --git a/distros/redhat/nginx/README.Fedora b/distros/redhat/nginx/README.Fedora
index 0a5168231..013a502b0 100644
--- a/distros/redhat/nginx/README.Fedora
+++ b/distros/redhat/nginx/README.Fedora
@@ -1,39 +1,34 @@
What's New
==========
-1. This is an *experimental* build of zoneminder which uses the
- nginx web server.
+1. See the ZoneMinder release notes for a list of new features:
+ https://github.com/ZoneMinder/zoneminder/releases
-2. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to
- "/cgi-bin-zm/zms". This has been to done to avoid this bug:
- https://bugzilla.redhat.com/show_bug.cgi?id=973067
+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.
- IMPORTANT: You must manually inspect the value for PATH_ZMS under Options
- and verify it is set to "/cgi-bin-zm/nph-zms". Failure to do so will result
- in a broken system. You have been warned.
-
-3. Due to the active state of the ZoneMinder project, we now recommend granting
- ALL permission to the ZoneMinder mysql account. This change must be done
- manually before ZoneMinder will run. See the installation steps below.
-
-4. This package uses the HTTPS protocol by default to access the web portal.
- Requests using HTTP will auto-redirect to HTTPS. See README.https for
- more information.
-
-5. This package ships with the new ZoneMinder API enabled.
+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 thie 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
============
-1. This package supports either community-mysql-server or mariadb-server with
- mariadb being the preferred choice. Unless you are already using MariaDB or
- Mysql server, you need to ensure that the server is configured to start
- during boot and properly secured by running:
+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 dnf install mariadb-server
- sudo systemctl enable mariadb
- sudo systemctl start mariadb.service
- mysql_secure_installation
+ sudo dnf install mariadb-server
+ sudo systemctl enable mariadb
+ sudo systemctl start mariadb.service
+ mysql_secure_installation
2. Assuming the database is local and using the password for the root account
set during the previous step, you will need to create the ZoneMinder
@@ -48,13 +43,17 @@ New installs
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 edit /etc/zm/zm.conf.
- Change ZM_DB_USER and ZM_DB_PASS to the values you created in the previous
- step.
+ 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}
- This version of zoneminder no longer requires you to make a similar change
- to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
- This now happens dynamically. Do *not* make any changes to this file.
+ 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
@@ -80,54 +79,87 @@ New installs
SELINUX line from "enforcing" to "disabled". This change will take
effect after a reboot.
-6. This package comes preconfigured for HTTPS using the default self signed
- certificate on your system. We recommend you keep this configuration.
+6. Configure the web server
- If this does not meet your needs, then read README.https to
- learn about alternatives.
+ 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.
-7. Edit /etc/sysconfig/fcgiwrap and set DAEMON_PROCS to the maximum number of
+ 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/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
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.
8. Now start the web server:
- sudo systemctl enable nginx
- sudo systemctl start nginx
+ sudo systemctl enable nginx
+ sudo systemctl start nginx
9. Now start zoneminder:
- sudo systemctl enable zoneminder
- sudo systemctl start zoneminder
+ sudo systemctl enable zoneminder
+ sudo systemctl start zoneminder
-10.The Fedora repos have a ZoneMinder package available, but it does not
- support ffmpeg or libvlc, which many modern IP cameras require. Most users
- will want to prevent the ZoneMinder package in the Fedora repos from
- overwriting the ZoneMinder package in zmrepo, during a future dnf update. To
- prevent that from happening you must edit /etc/yum.repos.d/fedora.repo
- and /etc/yum.repos.d/fedora-updates.repo. Add the line "exclude=zoneminder*"
- without the quotes under the [fedora] and [fedora-updates] blocks,
- respectively.
+10. 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.
+
+11. 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. Verify /etc/zm/zm.conf.
-
- If zm.conf was manually edited before running the upgrade, the installation
- may not overwrite it. In this case, it will create the file
- /etc/zm/zm.conf.rpmnew.
-
- For example, this will happen if you are using database account credentials
- other than zmuser/zmpass.
-
- Compare /etc/zm/zm.conf to /etc/zm/zm.conf.rpmnew. Verify that zm.conf
- contains any new config settings that may be in zm.conf.rpmnew.
-
- This version of zoneminder no longer requires you to make a similar change
- to the credentials in /usr/share/zoneminder/www/api/app/Config/database.php
- This now happens dynamically. Do *not* make any changes to this file.
+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.
@@ -139,12 +171,16 @@ Upgrades
See step 2 of the Installation section to add missing permissions.
-3. Verify the ZoneMinder Apache configuration file in the folder
- /etc/httpd/conf.d. You will have a file called "zoneminder.conf" and there
+3. Verify the ZoneMinder Nginx 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
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 Nginx 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:
diff --git a/distros/redhat/nginx/zoneminder.conf.in b/distros/redhat/nginx/zoneminder.conf.in
index b8ffd816a..cca9af54f 100644
--- a/distros/redhat/nginx/zoneminder.conf.in
+++ b/distros/redhat/nginx/zoneminder.conf.in
@@ -22,6 +22,10 @@ location /cgi-bin-zm {
fastcgi_pass unix:/run/fcgiwrap.sock;
}
+location /zm/cache {
+ alias "@ZM_CACHEDIR@";
+}
+
location /zm {
gzip off;
alias "@ZM_WEBDIR@";
diff --git a/distros/redhat/nginx/zoneminder.php-fpm.conf.in b/distros/redhat/nginx/zoneminder.php-fpm.conf.in
index 26e8c62cf..ffc44bbe0 100644
--- a/distros/redhat/nginx/zoneminder.php-fpm.conf.in
+++ b/distros/redhat/nginx/zoneminder.php-fpm.conf.in
@@ -1,10 +1,12 @@
-# Change the user and group of the default pool to the web server account
+; Change the user and group of the default pool to the web server account
[www]
user = @WEB_USER@
group = @WEB_GROUP@
-# Uncomment these on machines with little memory
-#pm = ondemand
-#pm.max_children = 10
-#pm.process_idle_timeout = 10s
+; These parameters are typically a tradoff between performance and memory
+; consumption. See the contents of www.conf for details.
+
+pm = ondemand
+pm.max_children = 50
+pm.process_idle_timeout = 10s
diff --git a/distros/redhat/nginx/zoneminder.tmpfiles.in b/distros/redhat/nginx/zoneminder.tmpfiles.in
index 8040a7877..07bae0900 100644
--- a/distros/redhat/nginx/zoneminder.tmpfiles.in
+++ b/distros/redhat/nginx/zoneminder.tmpfiles.in
@@ -1,5 +1,8 @@
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/zoneminder.spec b/distros/redhat/zoneminder.spec
index de1d408ea..05d0cf653 100644
--- a/distros/redhat/zoneminder.spec
+++ b/distros/redhat/zoneminder.spec
@@ -84,7 +84,8 @@ BuildRequires: libmp4v2-devel
BuildRequires: x264-devel
%{?with_nginx:Requires: nginx}
-%{?with_nginx:Requires: fcgiwrap}
+# Enable only after fcgiwrap is in Fedora repos
+#%{?with_nginx:Requires: fcgiwrap}
%{?with_nginx:Requires: php-fpm}
%{!?with_nginx:Requires: httpd}
%{!?with_nginx:Requires: php}
From 720505cbea163bf544b45cd861d6ae4592a174bb Mon Sep 17 00:00:00 2001
From: Andrew Bauer
Date: Sun, 4 Nov 2018 17:14:46 -0600
Subject: [PATCH 063/240] spelling
---
distros/redhat/nginx/README.Fedora | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/distros/redhat/nginx/README.Fedora b/distros/redhat/nginx/README.Fedora
index 013a502b0..90d760952 100644
--- a/distros/redhat/nginx/README.Fedora
+++ b/distros/redhat/nginx/README.Fedora
@@ -15,7 +15,7 @@ What's New
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 thie build of ZoneMinder
+ 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
From b8066e66ed6ab1b824fd6d058505c292d4873911 Mon Sep 17 00:00:00 2001
From: Andrew Bauer
Date: Mon, 5 Nov 2018 06:51:08 -0600
Subject: [PATCH 064/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 05d0cf653..4f51c73e4 100644
--- a/distros/redhat/zoneminder.spec
+++ b/distros/redhat/zoneminder.spec
@@ -307,7 +307,7 @@ EOF
%{_libexecdir}/zoneminder/
%{_datadir}/zoneminder/
-%{_datadir}/applications/*%{name}.desktop
+%{_datadir}/applications/*zoneminder.desktop
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder
%dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_sharedstatedir}/zoneminder/events
From d3064e440296152e66974f89a773ef0751e8f0a0 Mon Sep 17 00:00:00 2001
From: Andrew Bauer
Date: Mon, 5 Nov 2018 07:06:34 -0600
Subject: [PATCH 065/240] Update zoneminder.spec
---
distros/redhat/zoneminder.spec | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec
index 4f51c73e4..ecba0fb5a 100644
--- a/distros/redhat/zoneminder.spec
+++ b/distros/redhat/zoneminder.spec
@@ -84,8 +84,6 @@ BuildRequires: libmp4v2-devel
BuildRequires: x264-devel
%{?with_nginx:Requires: nginx}
-# Enable only after fcgiwrap is in Fedora repos
-#%{?with_nginx:Requires: fcgiwrap}
%{?with_nginx:Requires: php-fpm}
%{!?with_nginx:Requires: httpd}
%{!?with_nginx:Requires: php}
@@ -132,7 +130,7 @@ designed to support as many cameras as you can attach to your computer without
too much degradation of performance.
%prep
-%autosetup -p 1 -a 1 -n ZoneMinder-%{version}
+%autosetup -p 1 -a 1
%{__rm} -rf ./web/api/app/Plugin/Crud
%{__mv} -f crud-%{crud_version} ./web/api/app/Plugin/Crud
From ec951638105b320ac3a9940abe0b24f50f1d9b01 Mon Sep 17 00:00:00 2001
From: Andrew Bauer
Date: Mon, 5 Nov 2018 19:35:05 -0600
Subject: [PATCH 066/240] Add fedora 29 support to buildsystem
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index 1ae0988d5..d46e0fc85 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -38,6 +38,7 @@ env:
- OS=el DIST=7
- OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack
- OS=fedora DIST=28 DOCKER_REPO=knnniggett/packpack
+ - OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack
- OS=ubuntu DIST=trusty
- OS=ubuntu DIST=xenial
- OS=ubuntu DIST=trusty ARCH=i386
From c0c1247fa023e830345869fc86b9cff9abd817a0 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 10:33:55 -0500
Subject: [PATCH 067/240] bump verion to 1.32.2
---
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 32f052ecd..867942e4e 100644
--- a/distros/redhat/zoneminder.spec
+++ b/distros/redhat/zoneminder.spec
@@ -25,7 +25,7 @@
%global _hardened_build 1
Name: zoneminder
-Version: 1.32.1
+Version: 1.32.2
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
From 56bdd537575a3dd4531222ed6045707238266c70 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 10:40:44 -0500
Subject: [PATCH 068/240] Use the global dbh in ZoneMinder::Database instead of
keeping our own copy of it in Logger
---
scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm
index 16535d9e3..2d15c045d 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm
@@ -441,11 +441,11 @@ sub databaseLevel {
$databaseLevel = $this->limit($databaseLevel);
if ( $this->{databaseLevel} != $databaseLevel ) {
if ( ( $databaseLevel > NOLOG ) and ( $this->{databaseLevel} <= NOLOG ) ) {
- if ( !$this->{dbh} ) {
- $this->{dbh} = ZoneMinder::Database::zmDbConnect();
+ if ( ! ( $ZoneMinder::Database::dbh or ZoneMinder::Database::zmDbConnect() ) ) {
+ Warning("Failed connecting to db. Not using database logging.");
+ $this->{databaseLevel} = NOLOG;
+ return NOLOG;
}
- } elsif ( $databaseLevel <= NOLOG && $this->{databaseLevel} > NOLOG ) {
- undef($this->{dbh});
}
$this->{databaseLevel} = $databaseLevel;
}
@@ -558,12 +558,12 @@ sub logPrint {
}
if ( $level <= $this->{databaseLevel} ) {
- if ( ! ( $this->{dbh} and $this->{dbh}->ping() ) ) {
+ if ( ! ( $ZoneMinder::Database::dbh and $ZoneMinder::Database::dbh->ping() ) ) {
$this->{sth} = undef;
# Turn this off because zDbConnect will do logging calls.
my $oldlevel = $this->{databaseLevel};
$this->{databaseLevel} = NOLOG;
- if ( ! ( $this->{dbh} = ZoneMinder::Database::zmDbConnect() ) ) {
+ if ( ! ZoneMinder::Database::zmDbConnect() ) {
#print(STDERR "Can't log to database: ");
return;
}
@@ -571,10 +571,10 @@ sub logPrint {
}
my $sql = 'INSERT INTO Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, NULL )';
- $this->{sth} = $this->{dbh}->prepare_cached($sql) if ! $this->{sth};
+ $this->{sth} = $ZoneMinder::Database::dbh->prepare_cached($sql) if ! $this->{sth};
if ( !$this->{sth} ) {
$this->{databaseLevel} = NOLOG;
- Error("Can't prepare log entry '$sql': ".$this->{dbh}->errstr());
+ Error("Can't prepare log entry '$sql': ".$ZoneMinder::Database::dbh->errstr());
return;
}
@@ -590,7 +590,7 @@ sub logPrint {
);
if ( !$res ) {
$this->{databaseLevel} = NOLOG;
- Error("Can't execute log entry '$sql': ".$this->{dbh}->errstr());
+ Error("Can't execute log entry '$sql': ".$ZoneMinder::Database::dbh->errstr());
}
} # end if doing db logging
} # end if level < effectivelevel
From 0ebcef732491aece126378c8306a551e6929f8b6 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 11:01:12 -0500
Subject: [PATCH 069/240] in poddoc and over needs a =back
---
scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 2 ++
1 file changed, 2 insertions(+)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in
index d48747703..92085b07b 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in
@@ -309,6 +309,8 @@ saving configuration is a convenient way to ensure that the configuration
held in the database corresponds with the most recent definitions and that
all components are using the same set of configuration.
+=back
+
=head2 EXPORT
None by default.
From 4107082845e396fb3dff0cc762ec41c7cfc040ce Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 11:01:49 -0500
Subject: [PATCH 070/240] Don't delete default states if there are none
---
scripts/zmpkg.pl.in | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in
index b29235f65..2d6593619 100644
--- a/scripts/zmpkg.pl.in
+++ b/scripts/zmpkg.pl.in
@@ -315,17 +315,19 @@ 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' );
- $sql = "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() );
- $sql = q`"INSERT INTO States (Name,Definition,IsActive) VALUES ('default','','1');`;
+ 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() );
+ }
+ $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());
- }
+ }
# PP - Now make sure no two states have IsActive=1
$sql = 'SELECT Name FROM States WHERE IsActive = 1';
From 0e3eb0df17a64ddd09eef53bfae6c78ad508887f Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 11:26:48 -0500
Subject: [PATCH 071/240] remove extra quotes, google code style, update pod
docs
---
scripts/ZoneMinder/lib/ZoneMinder/General.pm | 150 ++++++++-----------
1 file changed, 65 insertions(+), 85 deletions(-)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/General.pm b/scripts/ZoneMinder/lib/ZoneMinder/General.pm
index 900a8985f..d16c248d5 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/General.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/General.pm
@@ -1,27 +1,3 @@
-# ==========================================================================
-#
-# ZoneMinder General Utility Module, $Date$, $Revision$
-# Copyright (C) 2001-2008 Philip Coombes
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# ==========================================================================
-#
-# This module contains the common definitions and functions used by the rest
-# of the ZoneMinder scripts
-#
package ZoneMinder::General;
use 5.006;
@@ -42,7 +18,7 @@ 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(
executeShellCommand
getCmdFormat
runCommand
@@ -56,7 +32,7 @@ our %EXPORT_TAGS = (
);
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();
@@ -80,74 +56,74 @@ sub executeShellCommand {
my $output = qx( $command );
my $status = $? >> 8;
if ( $status || logDebugging() ) {
- Debug( "Command: $command\n" );
+ Debug("Command: $command");
chomp( $output );
- Debug( "Output: $output\n" );
+ Debug("Output: $output");
}
- return( $status );
+ return $status;
}
sub getCmdFormat {
- Debug( "Testing valid shell syntax\n" );
+ Debug("Testing valid shell syntax");
my ( $name ) = getpwuid( $> );
if ( $name eq $Config{ZM_WEB_USER} ) {
- Debug( "Running as '$name', su commands not needed\n" );
- return( "" );
+ Debug("Running as '$name', su commands not needed");
+ return '';
}
- my $null_command = "true";
+ my $null_command = 'true';
- my $prefix = "sudo -u ".$Config{ZM_WEB_USER}." ";
- my $suffix = "";
+ my $prefix = 'sudo -u '.$Config{ZM_WEB_USER}.' ';
+ my $suffix = '';
my $command = $prefix.$null_command.$suffix;
- Debug( "Testing \"$command\"\n" );
+ Debug("Testing \"$command\"");
my $output = qx($command 2>&1);
my $status = $? >> 8;
$output //= $!;
if ( !$status ) {
- Debug( "Test ok, using format \"$prefix$suffix\"\n" );
+ Debug("Test ok, using format \"$prefix$suffix\"");
return( $prefix, $suffix );
} else {
chomp( $output );
- Debug( "Test failed, '$output'\n" );
+ Debug("Test failed, '$output'");
- $prefix = "su ".$Config{ZM_WEB_USER}." --shell=/bin/sh --command='";
- $suffix = "'";
+ $prefix = 'su '.$Config{ZM_WEB_USER}.q` --shell=/bin/sh --command='`;
+ $suffix = q`'`;
$command = $prefix.$null_command.$suffix;
- Debug( "Testing \"$command\"\n" );
+ Debug("Testing \"$command\"");
my $output = qx($command 2>&1);
my $status = $? >> 8;
$output //= $!;
if ( !$status ) {
- Debug( "Test ok, using format \"$prefix$suffix\"\n" );
+ Debug("Test ok, using format \"$prefix$suffix\"");
return( $prefix, $suffix );
} else {
- chomp( $output );
- Debug( "Test failed, '$output'\n" );
+ chomp($output);
+ Debug("Test failed, '$output'");
$prefix = "su ".$Config{ZM_WEB_USER}." -c '";
$suffix = "'";
$command = $prefix.$null_command.$suffix;
- Debug( "Testing \"$command\"\n" );
+ Debug("Testing \"$command\"");
$output = qx($command 2>&1);
$status = $? >> 8;
$output //= $!;
if ( !$status ) {
- Debug( "Test ok, using format \"$prefix$suffix\"\n" );
+ Debug("Test ok, using format \"$prefix$suffix\"");
return( $prefix, $suffix );
} else {
- chomp( $output );
- Debug( "Test failed, '$output'\n" );
+ chomp($output);
+ Debug("Test failed, '$output'");
}
}
}
- Error( "Unable to find valid 'su' syntax\n" );
- exit( -1 );
-}
+ Error("Unable to find valid 'su' syntax");
+ exit -1;
+} # end sub getCmdFormat
our $testedShellSyntax = 0;
our ( $cmdPrefix, $cmdSuffix );
@@ -161,23 +137,23 @@ sub runCommand {
}
my $command = shift;
- $command = $Config{ZM_PATH_BIN}."/".$command;
+ $command = $Config{ZM_PATH_BIN}.'/'.$command;
if ( $cmdPrefix ) {
$command = $cmdPrefix.$command.$cmdSuffix;
}
- Debug( "Command: $command\n" );
+ Debug("Command: $command");
my $output = qx($command);
my $status = $? >> 8;
- chomp( $output );
+ chomp($output);
if ( $status || logDebugging() ) {
if ( $status ) {
- Error( "Unable to run \"$command\", output is \"$output\", status is $status\n" );
+ Error("Unable to run \"$command\", output is \"$output\", status is $status");
} else {
- Debug( "Output: $output\n" );
+ Debug("Output: $output");
}
}
- return( $output );
-}
+ return $output;
+} # end sub runCommand
sub createEventPath {
my $event = shift;
@@ -210,7 +186,7 @@ sub _checkProcessOwner {
$_setFileOwner = 0;
}
}
- return( $_setFileOwner );
+ return $_setFileOwner;
}
sub setFileOwner {
@@ -219,7 +195,7 @@ sub setFileOwner {
if ( _checkProcessOwner() ) {
chown( $_ownerUid, $_ownerGid, $file )
or Fatal( "Can't change ownership of file '$file' to '"
- .$Config{ZM_WEB_USER}.":".$Config{ZM_WEB_GROUP}."': $!"
+ .$Config{ZM_WEB_USER}.':'.$Config{ZM_WEB_GROUP}."': $!"
);
}
}
@@ -234,13 +210,13 @@ sub _checkForImageInfo {
};
$_hasImageInfo = $@?0:1;
}
- return( $_hasImageInfo );
+ return $_hasImageInfo;
}
sub createEvent {
my $event = shift;
- Debug( "Creating event" );
+ Debug('Creating event');
#print( Dumper( $event )."\n" );
_checkForImageInfo();
@@ -561,38 +537,33 @@ __END__
=head1 NAME
-ZoneMinder::Database - Perl extension for blah blah blah
+ZoneMinder::General - Utility Functions for ZoneMinder
=head1 SYNOPSIS
-use ZoneMinder::Database;
+use ZoneMinder::General;
blah blah blah
=head1 DESCRIPTION
-Stub documentation for ZoneMinder, created by h2xs. It looks like the
-author of the extension was negligent enough to leave the stub
-unedited.
-
-Blah blah blah.
+This module contains the common definitions and functions used by the rest
+of the ZoneMinder scripts
=head2 EXPORT
-None by default.
+ functions => [ qw(
+ executeShellCommand
+ getCmdFormat
+ runCommand
+ setFileOwner
+ createEventPath
+ createEvent
+ makePath
+ jsonEncode
+ jsonDecode
+ ) ]
-
-=head1 SEE ALSO
-
-Mention other useful documentation such as the documentation of
-related modules or operating system documentation (such as man pages
- in UNIX), or any relevant external documentation such as RFCs or
-standards.
-
-If you have a mailing list set up for your module, mention it here.
-
-If you have a web site set up for your module, mention it here.
-
=head1 AUTHOR
Philip Coombes, Ephilip.coombes@zoneminder.comE
@@ -601,9 +572,18 @@ Philip Coombes, Ephilip.coombes@zoneminder.comE
Copyright (C) 2001-2008 Philip Coombes
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself, either Perl version 5.8.3 or,
-at your option, any later version of Perl 5 you may have available.
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
=cut
From 230ce61dc417506ecf38ee6ef509e2900ae4b1db Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 11:54:18 -0500
Subject: [PATCH 072/240] fix #2296 by prepending bind with ::
---
src/zm_stream.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp
index 7ab844d78..461a6d74d 100644
--- a/src/zm_stream.cpp
+++ b/src/zm_stream.cpp
@@ -325,7 +325,7 @@ void StreamBase::openComms() {
strncpy(loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path));
loc_addr.sun_family = AF_UNIX;
Debug(3, "Binding to %s", loc_sock_path);
- if ( bind(sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)+1) < 0 ) {
+ if ( ::bind(sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)+1) < 0 ) {
Fatal("Can't bind: %s", strerror(errno));
}
From a066968acaf3dd61f484c71b32c4d90736d8e67c Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 12:33:18 -0500
Subject: [PATCH 073/240] fix dbError and cause it to return the error string
instead of just logging it. Add error logging of db errors that don't throw
exceptions.
---
web/includes/database.php | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/web/includes/database.php b/web/includes/database.php
index 55535659f..95fabee11 100644
--- a/web/includes/database.php
+++ b/web/includes/database.php
@@ -98,7 +98,14 @@ function dbLog( $sql, $update=false ) {
}
function dbError( $sql ) {
- Error( "SQL-ERR '".$dbConn->errorInfo()."', statement was '".$sql."'" );
+ global $dbConn;
+ $error = $dbConn->errorInfo();
+ if ( ! $error[0] )
+ return '';
+
+ $message = "SQL-ERR '".implode("\n",$dbConn->errorInfo())."', statement was '".$sql."'";
+ Error($message);
+ return $message;
}
function dbEscape( $string ) {
@@ -136,6 +143,10 @@ function dbQuery( $sql, $params=NULL ) {
Logger::Debug("SQL: $sql values:" . ($params?implode(',',$params):'') );
}
$result = $dbConn->query($sql);
+ if ( ! $result ) {
+ Error("SQL: Error preparing $sql: " . $pdo->errorInfo);
+ return NULL;
+ }
}
if ( defined('ZM_DB_DEBUG') ) {
if ( $params )
From 702143e51bd8f0f52d9700491b8ca7e96665f66c Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 7 Nov 2018 12:33:54 -0500
Subject: [PATCH 074/240] Create a function called getBodyTopHTML that outputs
the body tag and anything else that should go at the top. Things like the we
require javascript message, and any other messages like error messages. Use
this on the monitor and console view to stick an error message at the top
when saving a monitor fails.
This is a pretty quick, crude implementation.
---
web/includes/actions.php | 4 +++-
web/index.php | 1 +
web/skins/classic/includes/functions.php | 22 +++++++++++++++++-----
web/skins/classic/views/console.php | 2 +-
web/skins/classic/views/monitor.php | 2 +-
5 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/web/includes/actions.php b/web/includes/actions.php
index de0861fe0..48082a585 100644
--- a/web/includes/actions.php
+++ b/web/includes/actions.php
@@ -554,7 +554,8 @@ if ( canEdit('Monitors') ) {
$maxSeq = dbFetchOne('SELECT MAX(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence');
$changes[] = 'Sequence = '.($maxSeq+1);
- if ( dbQuery('INSERT INTO Monitors SET '.implode(', ', $changes)) ) {
+ $sql = 'INSERT INTO Monitors SET '.implode(', ', $changes);
+ if ( dbQuery($sql) ) {
$mid = dbInsertId();
$zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height'];
dbQuery("INSERT INTO Zones SET MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) );
@@ -566,6 +567,7 @@ if ( canEdit('Monitors') ) {
} else {
Error('Error saving new Monitor.');
+ $error_message = dbError($sql);
return;
}
} else {
diff --git a/web/index.php b/web/index.php
index addddce06..cbda1096a 100644
--- a/web/index.php
+++ b/web/index.php
@@ -170,6 +170,7 @@ if ( !is_writable(ZM_DIR_EVENTS) || !is_writable(ZM_DIR_IMAGES) ) {
}
# Globals
+$error_message = null;
$redirect = null;
$view = null;
if ( isset($_REQUEST['view']) )
diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php
index 7847e37c7..8fd9e2a8e 100644
--- a/web/skins/classic/includes/functions.php
+++ b/web/skins/classic/includes/functions.php
@@ -208,6 +208,23 @@ echo output_link_if_exists( array(
+
+';
+ global $error_message;
+ if ( $error_message ) {
+ echo '
'.$error_message.'
';
+ }
+} // end function getBodyTopHTML
+
function getNavBarHTML($reload = null) {
# Provide a facility to turn off the headers if you put headers=0 into the url
if ( isset($_REQUEST['navbar']) and $_REQUEST['navbar']=='0' )
@@ -235,11 +252,6 @@ function getNavBarHTML($reload = null) {
$running = daemonCheck();
$status = $running?translate('Running'):translate('Stopped');
?>
-
From 1844a7eb292dec6188af0836feaea938b99537a7 Mon Sep 17 00:00:00 2001
From: Aktarus <11706557+aktarus82@users.noreply.github.com>
Date: Fri, 9 Nov 2018 13:59:06 +0100
Subject: [PATCH 077/240] Update definemonitor.rst (#2299)
---
docs/userguide/definemonitor.rst | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/docs/userguide/definemonitor.rst b/docs/userguide/definemonitor.rst
index bf12a1bc5..bcd195570 100644
--- a/docs/userguide/definemonitor.rst
+++ b/docs/userguide/definemonitor.rst
@@ -164,6 +164,29 @@ Height (pixels)
Web Site Refresh
If the website in question has static content, optionally enter a time period in seconds for ZoneMinder to refresh the content.
+Storage Tab
+-----------
+
+The storage section allows for each monitor to configure if and how video and audio are recorded.
+
+Save JPEGs
+ Records video in individual JPEG frames. Storing JPEG frames requires more storage space than h264 but it allows to view an event anytime while it is being recorded.
+
+ * Disabled – video is not recorded as JPEG frames. If this setting is selected, then "Video Writer" should be enabled otherwise there is no video recording at all.
+ * Frames only – video is recorded in individual JPEG frames.
+ * Analysis images only (if available) – video is recorded in invidual JPEG frames with an overlay of the motion detection analysis information. Note that this overlay remains permanently visible in the frames.
+ * Frames + Analysis images (if available) – video is recorded twice, once as normal individual JPEG frames and once in invidual JPEG frames with analysis information overlaid.
+
+Video Writer
+ Records video in real video format. It provides much better compression results than saving JPEGs, thus longer video history can be stored.
+
+ * Disabled – video is not recorded in video format. If this setting is selected, then "Save JPEGs" should be enabled otherwise there is no video recording at all.
+ * X264 Encode – the video or picture frames received from the camera are transcoded into h264 and stored as a video. This option is useful if the camera cannot natively stream h264.
+ * H264 Camera Passthrough – this option assumes that the camera is already sending an h264 stream. Video will be recorded as is, without any post-processing in zoneminder. Video characteristics such as bitrate, encoding mode, etc. should be set directly in the camera.
+
+Recording Audio
+ Check the box labeled "Whether to store the audio stream when saving an event." in order to save audio (if available) when events are recorded.
+
Timestamp Tab
-------------
From 4ddd328c6186b1e40286994efed0f24b46023ea0 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 9 Nov 2018 10:39:57 -0500
Subject: [PATCH 078/240] Check and Fix Scheme and StorageArea
---
scripts/zmaudit.pl.in | 110 ++++++++++++++++++++++--------------------
1 file changed, 59 insertions(+), 51 deletions(-)
diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in
index 495fdc031..66dab7ae4 100644
--- a/scripts/zmaudit.pl.in
+++ b/scripts/zmaudit.pl.in
@@ -508,68 +508,76 @@ MAIN: while( $loop ) {
# Foreach database monitor and it's list of events.
while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) ) {
+ Debug("Checking db events for monitor $db_monitor");
+ if ( ! $db_events ) {
+ Debug("Skipping db events for $db_monitor because there are none");
+ next;
+ }
# If we found the monitor in the file system
- if ( my $fs_events = $fs_monitors->{$db_monitor} ) {
- next if ! $db_events;
+ my $fs_events = $fs_monitors->{$db_monitor};
- while ( my ( $db_event, $age ) = each( %$db_events ) ) {
- if ( ! defined( $fs_events->{$db_event} ) ) {
- my $Event = ZoneMinder::Event->find_one( Id=>$db_event );
- if ( ! $Event ) {
- Debug("Event $db_event is no longer in db. Filter probably deleted it while we were auditing.");
- next;
+ while ( my ( $db_event, $age ) = each( %$db_events ) ) {
+ if ( ! ($fs_events and defined( $fs_events->{$db_event} ) ) ) {
+ Debug("Don't have an fs event for $db_event");
+ my $Event = ZoneMinder::Event->find_one( Id=>$db_event );
+ if ( ! $Event ) {
+ Debug("Event $db_event is no longer in db. Filter probably deleted it while we were auditing.");
+ next;
+ }
+ Debug("Event $db_event is not in fs. Should have been at ".$Event->Path());
+ if ( $Event->Archived() ) {
+ Warning("Event $$Event{Id} is Archived. Taking no further action on it.");
+ next;
+ }
+ if ( ! $Event->StartTime() ) {
+ Info("Event $$Event{Id} has no start time. deleting it.");
+ if ( confirm() ) {
+ $Event->delete();
+ $cleaned = 1;
}
- Debug("Event $db_event is not in fs. Should have been at ".$Event->Path());
- if ( $Event->Archived() ) {
- Warning("Event $$Event{Id} is Archived. Taking no further action on it.");
- next;
- }
- if ( ! $Event->StartTime() ) {
- Info("Event $$Event{Id} has no start time. deleting it.");
+ next;
+ }
+ if ( ! $Event->EndTime() ) {
+ if ( $age > $Config{ZM_AUDIT_MIN_AGE} ) {
+ Info("Event $$Event{Id} has no end time and is $age seconds old. deleting it.");
if ( confirm() ) {
$Event->delete();
$cleaned = 1;
}
next;
- }
- if ( ! $Event->EndTime() ) {
- if ( $age > $Config{ZM_AUDIT_MIN_AGE} ) {
- Info("Event $$Event{Id} has no end time and is $age seconds old. deleting it.");
- if ( confirm() ) {
- $Event->delete();
- $cleaned = 1;
- }
- next;
- }
}
- if ( $Event->check_for_in_filesystem() ) {
- Debug("Database event $$Event{Id} apparently exists at " . $Event->Path() );
- } else {
- if ( $age > $Config{ZM_AUDIT_MIN_AGE} ) {
- aud_print( "Database event '$db_monitor/$db_event' does not exist at " . $Event->Path().' in filesystem, deleting' );
- if ( confirm() ) {
- $Event->delete();
- $cleaned = 1;
- }
- } else {
- aud_print( "Database event '".$Event->Path()." monitor:$db_monitor event:$db_event' does not exist in filesystem but too young to delete age: $age > MIN $Config{ZM_AUDIT_MIN_AGE}.\n" );
+ }
+ if ( $Event->check_for_in_filesystem() ) {
+ Debug("Database event $$Event{Id} apparently exists at " . $Event->Path() );
+ } else {
+ if ( $age > $Config{ZM_AUDIT_MIN_AGE} ) {
+ aud_print( "Database event '$db_monitor/$db_event' does not exist at " . $Event->Path().' in filesystem, deleting' );
+ if ( confirm() ) {
+ $Event->delete();
+ $cleaned = 1;
}
- } # end if exists in filesystem
- } # end if ! in fs_events
- } # foreach db_event
- #} else {
- #my $Monitor = new ZoneMinder::Monitor( $db_monitor );
- #my $Storage = $Monitor->Storage();
- #aud_print( "Database monitor '$db_monitor' does not exist in filesystem, should have been at ".$Storage->Path().'/'.$Monitor->Id()."\n" );
-#if ( confirm() )
-#{
-# We don't actually do this in case it's new
-#my $res = $deleteMonitorSth->execute( $db_monitor )
-# or Fatal( "Can't execute: ".$deleteMonitorSth->errstr() );
-#$cleaned = 1;
-#}
- }
+ } else {
+ aud_print( "Database event '".$Event->Path()." monitor:$db_monitor event:$db_event' does not exist in filesystem but too young to delete age: $age > MIN $Config{ZM_AUDIT_MIN_AGE}.\n" );
+ }
+ } # end if exists in filesystem
+ } else {
+ Debug("Found fs event for $db_event, $age at " . $$fs_events{$db_event}->Path());
+ my $Event = new ZoneMinder::Event( $db_event );
+ if ( ! $Event->check_for_in_filesystem() ) {
+ Warning("Not found at " . $Event->Path() );
+ if ( $$fs_events{$db_event}->Scheme() ne $Event->Scheme() ) {
+ Info("Updating scheme on event $$Event{Id} from $$Event{Scheme} to $$fs_events{$db_event}{Scheme}");
+ $Event->Scheme($$fs_events{$db_event}->Scheme());
+ }
+ if ( $$fs_events{$db_event}->StorageId() != $Event->StorageId() ) {
+ Info("Updating storage area on event $$Event{Id} from $$Event{StorageId} to $$fs_events{$db_event}{StorageId}");
+ $Event->StorageId($$fs_events{$db_event}->StorageId());
+ }
+ $Event->save();
+ }
+ } # end if ! in fs_events
+ } # foreach db_event
} # end foreach db_monitor
if ( $cleaned ) {
Debug("Have done some cleaning, restarting.");
From 5f81e9111f6e8e4b4ba2030e983babf3fb9a6bdf Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 9 Nov 2018 12:14:05 -0500
Subject: [PATCH 079/240] Add Scheme and SaveJPEGs to Event fields, and fix
setting Scheme
---
scripts/ZoneMinder/lib/ZoneMinder/Event.pm | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm
index d52c9829e..67cd850b9 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm
@@ -70,6 +70,7 @@ $serial = $primary_key = 'Id';
Frames
AlarmFrames
DefaultVideo
+ SaveJPEGs
TotScore
AvgScore
MaxScore
@@ -83,6 +84,7 @@ $serial = $primary_key = 'Id';
StateId
Orientation
DiskSpace
+ Scheme
);
use POSIX;
@@ -168,6 +170,8 @@ sub Path {
sub Scheme {
my $self = shift;
+ $$self{Scheme} = shift if @_;
+
if ( ! $$self{Scheme} ) {
if ( $$self{RelativePath} ) {
if ( $$self{RelativePath} =~ /^\d+\/\d{4}\-\d{2}\-\d{2}\/\d+$/ ) {
From 1e98ecb5957a69970da2cadcea1412e0a217e220 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 9 Nov 2018 12:14:39 -0500
Subject: [PATCH 080/240] Sort keys in to_string
---
scripts/ZoneMinder/lib/ZoneMinder/Object.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Object.pm b/scripts/ZoneMinder/lib/ZoneMinder/Object.pm
index 8c28028a0..f779255b2 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Object.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Object.pm
@@ -456,7 +456,7 @@ sub transform {
sub to_string {
my $type = ref($_[0]);
my $fields = eval '\%'.$type.'::fields';
- return $type . ': '. join(' ' , map { $_[0]{$_} ? "$_ => $_[0]{$_}" : () } keys %$fields );
+ return $type . ': '. join(' ' , map { $_[0]{$_} ? "$_ => $_[0]{$_}" : () } sort { $a cmp $b } keys %$fields );
}
1;
From 967fe14b22dde95e07f7041655af2b2239aff218 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Sun, 11 Nov 2018 10:17:32 -0500
Subject: [PATCH 081/240] Add ability to update incorrect starttime.
---
scripts/zmaudit.pl.in | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in
index 66dab7ae4..ebd56229e 100644
--- a/scripts/zmaudit.pl.in
+++ b/scripts/zmaudit.pl.in
@@ -509,10 +509,10 @@ MAIN: while( $loop ) {
# Foreach database monitor and it's list of events.
while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) ) {
Debug("Checking db events for monitor $db_monitor");
- if ( ! $db_events ) {
- Debug("Skipping db events for $db_monitor because there are none");
- next;
- }
+ if ( ! $db_events ) {
+ Debug("Skipping db events for $db_monitor because there are none");
+ next;
+ }
# If we found the monitor in the file system
my $fs_events = $fs_monitors->{$db_monitor};
@@ -565,7 +565,9 @@ MAIN: while( $loop ) {
Debug("Found fs event for $db_event, $age at " . $$fs_events{$db_event}->Path());
my $Event = new ZoneMinder::Event( $db_event );
if ( ! $Event->check_for_in_filesystem() ) {
- Warning("Not found at " . $Event->Path() );
+ Warning("Not found at " . $Event->Path() . ' was found at ' . $$fs_events{$db_event}->Path() );
+ Warning($Event->to_string());
+ Warning($$fs_events{$db_event}->to_string());
if ( $$fs_events{$db_event}->Scheme() ne $Event->Scheme() ) {
Info("Updating scheme on event $$Event{Id} from $$Event{Scheme} to $$fs_events{$db_event}{Scheme}");
$Event->Scheme($$fs_events{$db_event}->Scheme());
@@ -574,6 +576,15 @@ MAIN: while( $loop ) {
Info("Updating storage area on event $$Event{Id} from $$Event{StorageId} to $$fs_events{$db_event}{StorageId}");
$Event->StorageId($$fs_events{$db_event}->StorageId());
}
+ if ( $$fs_events{$db_event}->StartTime() ne $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->save();
+ }
+
$Event->save();
}
} # end if ! in fs_events
@@ -962,7 +973,7 @@ sub delete_empty_directories {
return;
}
my @contents = map { ( $_ eq '.' or $_ eq '..' ) ? () : $_ } readdir( $DIR );
- Debug("delete_empty_directories $_[0] has " . @contents .' entries:' . ( @contents <= 2 ? join(',',@contents) : '' ));
+ #Debug("delete_empty_directories $_[0] has " . @contents .' entries:' . ( @contents <= 2 ? join(',',@contents) : '' ));
my @dirs = map { -d $_[0].'/'.$_ ? $_ : () } @contents;
if ( @dirs ) {
Debug("Have " . @dirs . " dirs");
From 246765ced975e4b5c4ef120c185c0bed91deb511 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Sun, 11 Nov 2018 16:23:19 -0500
Subject: [PATCH 082/240] Add tooltip for sorting monitors
---
web/skins/classic/views/console.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php
index 46575ffa0..1ebf49136 100644
--- a/web/skins/classic/views/console.php
+++ b/web/skins/classic/views/console.php
@@ -324,7 +324,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
?>
disabled="disabled"/>
-
+
Date: Mon, 12 Nov 2018 06:18:13 -0800
Subject: [PATCH 083/240] Fix typos in README file (#2301)
* Fix typos in README file
* Improve clarity in introduction doc
* Improved word selection
* Revision of the README file
* Finish editing introduction documentation
---
README.md | 4 ++--
docs/userguide/introduction.rst | 13 ++++++-------
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index 94774364c..b8e3f34fd 100644
--- a/README.md
+++ b/README.md
@@ -53,9 +53,9 @@ Lastly, if you desire to build a development snapshot from the master branch, it
Please visit our [ReadtheDocs site](https://zoneminder.readthedocs.org/en/stable/installationguide/index.html) for distro specific instructions.
### Package Maintainers
-Many of the ZoneMinder configration variable default values are not configurable at build time through autotools or cmake. A new tool called *zmeditconfigdata.sh* has been added to allow package maintainers to manipulate any variable stored in ConfigData.pm without patching the source.
+Many of the ZoneMinder configuration variable default values are not configurable at build time through autotools or cmake. A new tool called *zmeditconfigdata.sh* has been added to allow package maintainers to manipulate any variable stored in ConfigData.pm without patching the source.
-For example, let's say I have created a new ZoneMinder package that contains the cambozola javascript file. However, by default cambozola support is turned off. To fix that, add this to the pacakging script:
+For example, let's say I have created a new ZoneMinder package that contains the cambozola javascript file. However, by default cambozola support is turned off. To fix that, add this to the packaging script:
```bash
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
```
diff --git a/docs/userguide/introduction.rst b/docs/userguide/introduction.rst
index 8da67a5e9..2d9985eb1 100644
--- a/docs/userguide/introduction.rst
+++ b/docs/userguide/introduction.rst
@@ -1,15 +1,14 @@
Introduction
============
-Welcome to ZoneMinder, the all-in-one Linux GPL'd security camera solution.
+Welcome to ZoneMinder, the all-in-one security camera solution for Linux with GPL License.
-Most commercial "security systems" are designed as a monitoring system that also records. Recording quality can vary from bad to unusable, locating the relevant video can range from challenging to impractical, and exporting can often only be done with the manual present. ZoneMinder was designed primarily to record, and allow easy searches and exporting. Recordings are of the best possible quality, easy to filter and find, and simple to export using any system with a web browser. It also monitors.
+Commercial "security systems" are often designed as a monitoring system with little attention to recording quality. In such a system, locating and exporting relevant video can be challenging and often requires extensive human intervention. ZoneMinder was designed to provide the best possible record quality while allowing easy searching, filtering and exporting of security footage.
-ZoneMinder is designed around a series of independent components that only function when necessary limiting any wasted resource and maximising the efficiency of your machine. A fairly ancient Pentium II PC should be able to track one camera per device at up to 25 frames per second with this dropping by half approximately for each additional camera on the same device. Additional cameras on other devices do not interact so can maintain this frame rate. Even monitoring several cameras still will not overload the CPU as frame processing is designed to synchronise with capture and not stall it.
+ZoneMinder is designed around a series of independent components that only function when necessary, limiting any wasted resource and maximising the efficiency of your machine. An outdated Pentium II PC can have multiple recording devices connected to it, and it is able to track one camera per device at up to 25 frames per second, which drops by approximately half for each additional camera on the same device. Additional cameras on devices that do not interact with other devices can maintain the 25 frame rate per second. Monitoring several cameras will not overload the CPU as frame processing is designed to synchronise with capture.
-As well as being fast ZoneMinder is designed to be friendly and even more than that, actually useful. As well as the fast video interface core it also comes with a user friendly and comprehensive PHP based web interface allowing you to control and monitor your cameras from home, at work, on the road, or even a web enabled cell phone. It supports variable web capabilities based on available bandwidth. The web interface also allows you to view events that your cameras have captured and archive them or review them time and again, or delete the ones you no longer wish to keep. The web pages directly interact with the core daemons ensuring full co-operation at all times. ZoneMinder can even be installed as a system service ensuring it is right there if your computer has to reboot for any reason.
+A fast video interface core, a user-friendly and comprehensive PHP based web interface allows ZoneMinder to be efficient, friendly and most importantly useful. You can control and monitor your cameras from home, at work, on the road, or a web-enabled cell phone. It supports variable web capabilities based on available bandwidth. The web interface also allows you to view events that your cameras have captured, which can be archived, reviewed or deleted. The web application directly interacts with the core daemons ensuring full co-operation at all times. ZoneMinder can also be installed as a system service to reboot a system remotely.
-The core of ZoneMinder is the capture and analysis of images and there is a highly configurable set of parameters that allow you to ensure that you can eliminate false positives whilst ensuring that anything you don't want to miss will be captured and saved. ZoneMinder allows you to define a set of 'zones' for each camera of varying sensitivity and functionality. This allows you to eliminate regions that you don't wish to track or define areas that will alarm if various thresholds are exceeded in conjunction with other zones.
-
-ZoneMinder is free, but if you do find it useful then please feel free to visit http://www.zoneminder.com/donate.html and help to fund future improvements to ZoneMinder.
+The core of ZoneMinder is the capture and analysis of images and a highly configurable set of parameters that eliminate false positives whilst ensuring minimum loss of footage. For example, you can define a set of 'zones' for each camera of varying sensitivity and functionality. This eliminates zones that you don't wish to track or define areas that will alarm if various thresholds are exceeded in conjunction with other zones.
+ZoneMinder is free under GPL License, but if you do find it useful, then please feel free to visit http://www.zoneminder.com/donate.html and help us fund our future improvements.
From a95a012fa5dbe9da7b126d04be46f941c1d7f96d Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 12 Nov 2018 11:56:18 -0500
Subject: [PATCH 084/240] fix #2302
---
src/zm_monitor.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp
index 2e1e55691..8ff0a0a64 100644
--- a/src/zm_monitor.cpp
+++ b/src/zm_monitor.cpp
@@ -2110,6 +2110,7 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
Camera *camera = 0;
if ( type == "Local" ) {
+#if ZM_HAS_V4L
int extras = (deinterlacing>>24)&0xff;
camera = new LocalCamera(
@@ -2132,6 +2133,9 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
record_audio,
extras
);
+#else
+ Fatal("ZoneMinder not built with Local Camera support");
+#endif
} else if ( type == "Remote" ) {
if ( protocol == "http" ) {
camera = new RemoteCameraHttp(
From 01a57222d3cecc53751bf2405617242bc74fab19 Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Mon, 12 Nov 2018 12:43:20 -0500
Subject: [PATCH 085/240] keep track if we have written alarmed frame incase
savejpeg is off
---
src/zm_event.cpp | 8 ++++++++
src/zm_event.h | 1 +
web/views/image.php | 36 ++++++++++++++++++++----------------
3 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/src/zm_event.cpp b/src/zm_event.cpp
index 8d3108b31..20f7902f3 100644
--- a/src/zm_event.cpp
+++ b/src/zm_event.cpp
@@ -117,6 +117,7 @@ Event::Event(
alarm_frames = 0;
tot_score = 0;
max_score = 0;
+ alarm_frame_written = false;
char id_file[PATH_MAX];
@@ -527,6 +528,13 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
WriteFrameImage(image, timestamp, snapshot_file);
}
+ // The first frame with a score will be the frame that alarmed the event
+ if (!alarm_frame_written && score > 0) {
+ alarm_frame_written = true;
+ char alarm_file[PATH_MAX];
+ snprintf(alarm_file, sizeof(alarm_file), "%s/alarm.jpg", path);
+ WriteFrameImage(image, timestamp, alarm_file);
+ }
}
if ( videowriter != NULL ) {
Debug(3, "Writing video");
diff --git a/src/zm_event.h b/src/zm_event.h
index 1e55ae593..95595f689 100644
--- a/src/zm_event.h
+++ b/src/zm_event.h
@@ -82,6 +82,7 @@ class Event {
bool videoEvent;
int frames;
int alarm_frames;
+ static bool alarm_frame_written;
unsigned int tot_score;
unsigned int max_score;
char path[PATH_MAX];
diff --git a/web/views/image.php b/web/views/image.php
index 2c04f18e6..16c88f908 100644
--- a/web/views/image.php
+++ b/web/views/image.php
@@ -69,7 +69,7 @@ if ( empty($_REQUEST['path']) ) {
}
if ( !empty($_REQUEST['eid']) ) {
-Logger::Debug("Loading by eid");
+ Logger::Debug("Loading by eid");
$Event = Event::find_one(array('Id'=>$_REQUEST['eid']));
if ( !$Event ) {
header('HTTP/1.0 404 Not Found');
@@ -77,24 +77,28 @@ Logger::Debug("Loading by eid");
return;
}
- # if alarm, get the fid of the first alarmed frame if available and let the
- # fid= code continue processing it. Sort it to get the first alarmed frame
if ( $_REQUEST['fid'] == 'alarm' ) {
+ # look for first alarmed frame
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'Type'=>'Alarm'),
array('order'=>'FrameId ASC'));
- if ( !$Frame ) # no alarms
- $Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'])); # first frame
- if ( !$Frame ) {
- Warning("No frame found for event " + $_REQUEST['eid']);
- $Frame = new Frame();
- $Frame->Delta(1);
- $Frame->FrameId('snapshot');
+ if ( !$Frame ) { # no alarms, get first one I find
+ $Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid']));
+ if ( !$Frame ) {
+ Warning("No frame found for event " + $_REQUEST['eid']);
+ $Frame = new Frame();
+ $Frame->Delta(1);
+ $Frame->FrameId(1);
+ }
+ }
+ $Monitor = $Event->Monitor();
+ if ( $Monitor->SaveJPEGs() & 1 ) {
+ # If we store Frames as jpgs, then we don't store an alarmed snapshot
+ $path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
+ } else {
+ $path = $Event->Path().'/alarm.jpg';
}
- $_REQUEST['fid']=$Frame->FrameId();
}
-
-
- if ( $_REQUEST['fid'] == 'snapshot' ) {
+ else if ( $_REQUEST['fid'] == 'snapshot' ) {
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'Score'=>$Event->MaxScore()));
if ( !$Frame )
$Frame = Frame::find_one(array('EventId'=>$_REQUEST['eid']));
@@ -130,14 +134,14 @@ Logger::Debug("Loading by eid");
$percentage = ($Frame->FrameId() - $previousBulkFrame['FrameId']) / ($nextBulkFrame['FrameId'] - $previousBulkFrame['FrameId']);
$Frame->Delta($previousBulkFrame['Delta'] + floor( 100* ( $nextBulkFrame['Delta'] - $previousBulkFrame['Delta'] ) * $percentage )/100);
-Logger::Debug("Got virtual frame from Bulk Frames previous delta: " . $previousBulkFrame['Delta'] . " + nextdelta:" . $nextBulkFrame['Delta'] . ' - ' . $previousBulkFrame['Delta'] . ' * ' . $percentage );
+ Logger::Debug("Got virtual frame from Bulk Frames previous delta: " . $previousBulkFrame['Delta'] . " + nextdelta:" . $nextBulkFrame['Delta'] . ' - ' . $previousBulkFrame['Delta'] . ' * ' . $percentage );
} else {
Fatal('No Frame found for event('.$_REQUEST['eid'].') and frame id('.$_REQUEST['fid'].')');
}
}
// Frame can be non-existent. We have Bulk frames. So now we should try to load the bulk frame
$path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
-Logger::Debug("Path: $path");
+ Logger::Debug("Path: $path");
}
} else {
From e06f5b0f902a5d8cbaa18e52fce73edc7ea280a5 Mon Sep 17 00:00:00 2001
From: Pliable Pixels
Date: Mon, 12 Nov 2018 13:34:29 -0500
Subject: [PATCH 086/240] removed static
---
src/zm_event.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/zm_event.h b/src/zm_event.h
index 95595f689..7c38764bc 100644
--- a/src/zm_event.h
+++ b/src/zm_event.h
@@ -82,7 +82,7 @@ class Event {
bool videoEvent;
int frames;
int alarm_frames;
- static bool alarm_frame_written;
+ bool alarm_frame_written;
unsigned int tot_score;
unsigned int max_score;
char path[PATH_MAX];
From d76d6bb9d13bcbbb98adb35122c0cda2d859e938 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 12 Nov 2018 15:09:15 -0500
Subject: [PATCH 087/240] include overlay.js when viewing the log, so that
export works
---
web/skins/classic/includes/functions.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php
index 7847e37c7..b21157607 100644
--- a/web/skins/classic/includes/functions.php
+++ b/web/skins/classic/includes/functions.php
@@ -192,7 +192,7 @@ 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' ) {
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
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
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
"},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