diff --git a/.github/support.yml b/.github/support.yml new file mode 100644 index 000000000..fc61e151e --- /dev/null +++ b/.github/support.yml @@ -0,0 +1,27 @@ +# Configuration for support-requests - https://github.com/dessant/support-requests + +# Label used to mark issues as support requests +supportLabel: support + +# Comment to post on issues marked as support requests, `{issue-author}` is an +# optional placeholder. Set to `false` to disable +supportComment: > + :wave: @{issue-author}, we use the issue tracker exclusively for bug reports. + However, this issue appears to be a support request, a feature request, or + attempts to ask a question. + + Please use our support channels to get help with or discuss this project: + - The [ZoneMinder-Chat Slack channel](https://zoneminder-chat.herokuapp.com/) + - The [ZoneMinder Forum](https://forums.zoneminder.com/) + +# Close issues marked as support requests +close: true + +# Lock issues marked as support requests +lock: true + +# Assign `off-topic` as the reason for locking. Set to `false` to disable +setLockReason: true + +# Repository to extend settings from +# _extends: repo diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d070c6d3..46f3b0372 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,8 @@ mark_as_advanced( ZM_PATH_ARP ZM_CONFIG_DIR ZM_CONFIG_SUBDIR - ZM_SYSTEMD) + ZM_SYSTEMD + ZM_MANPAGE_DEST_PREFIX) set(ZM_RUNDIR "/var/run/zm" CACHE PATH "Location of transient process files, default: /var/run/zm") @@ -210,6 +211,10 @@ set(ZM_TARGET_DISTRO "" CACHE STRING "Build ZoneMinder for a specific distribution. Currently, valid names are: fc27, fc26, el7, OS13, FreeBSD") set(ZM_SYSTEMD "OFF" CACHE BOOL "Set to ON to force building ZM with systemd support. default: OFF") +set(ZM_MANPAGE_DEST_PREFIX "share/man" CACHE PATH + "Relative path used to install ZoneMinder's Man pages into a + non-standard folder. Most Linux users will not need to change this. + BSD users may need to set this.") # Reassign some variables if a target distro has been specified if((ZM_TARGET_DISTRO MATCHES "^el") OR (ZM_TARGET_DISTRO MATCHES "^fc")) diff --git a/cmake/Modules/Pod2Man.cmake b/cmake/Modules/Pod2Man.cmake index 6804fab53..734be239b 100644 --- a/cmake/Modules/Pod2Man.cmake +++ b/cmake/Modules/Pod2Man.cmake @@ -21,7 +21,7 @@ # To use it, include this file in CMakeLists.txt and # invoke POD2MAN(
) -MACRO(POD2MAN PODFILE MANFILE SECTION) +MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX) FIND_PROGRAM(POD2MAN pod2man) FIND_PROGRAM(GZIP gzip) @@ -58,9 +58,9 @@ MACRO(POD2MAN PODFILE MANFILE SECTION) INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz - DESTINATION share/man/man${SECTION} + DESTINATION ${MANPAGE_DEST_PREFIX}/man${SECTION} ) -ENDMACRO(POD2MAN PODFILE MANFILE SECTION) +ENDMACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX) MACRO(ADD_MANPAGE_TARGET) # It is not possible add a dependency to target 'install' diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index e9f0ca9ab..26d31dd2f 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.33.0.sql b/db/zm_update-1.33.0.sql new file mode 100644 index 000000000..cc7a257c7 --- /dev/null +++ b/db/zm_update-1.33.0.sql @@ -0,0 +1,21 @@ +-- +-- This updates a 1.32.3 database to 1.33.0 +-- +-- +-- Remove DefaultView from Monitors table. +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Monitors' + AND table_schema = DATABASE() + AND column_name = 'DefaultView' + ) > 0, +"ALTER TABLE Monitors DROP COLUMN DefaultView", +"SELECT 'Column DefaultView no longer exists in Monitors'" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 941bad900..cbda079ca 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -23,7 +23,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.32.3 +Version: 1.33.0 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons @@ -411,6 +411,9 @@ EOF %dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload %changelog +* Tue Dec 11 2018 Andrew Bauer - 1.33.0-1 +- Bump tp 1.33.0 Development + * Sat Dec 08 2018 Andrew Bauer - 1.32.3-1 - 1.32.3 Release - Break into sub-packages diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index e278c3eaf..bd1885fbe 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -32,7 +32,7 @@ configure_file(zm.in "${CMAKE_CURRENT_BINARY_DIR}/zm" @ONLY) file(GLOB perlscripts "*.pl") FOREACH(PERLSCRIPT ${perlscripts}) get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME) - POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8) + POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX}) ENDFOREACH(PERLSCRIPT ${perlscripts}) # Install the perl scripts diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index eac13cb75..27d993894 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -1202,6 +1202,20 @@ our @options = ( category => 'logging', }, { + name => 'ZM_LOG_FFMPEG', + default => 'yes', + description => 'Log FFMPEG messages', + help => q` + When enabled (default is on), this option will log FFMPEG messages. + FFMPEG messages can be useful when debugging streaming issues. However, + depending on your distro and FFMPEG version, this may also result in + more logs than you'd typically like to see. If all your streams are working + well, you may choose to turn this off. + `, + type => $types{boolean}, + category => 'logging', + }, +{ name => 'ZM_LOG_DEBUG', default => 'no', description => 'Switch debugging on', diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 124dab1ba..6d2b2d945 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -310,7 +310,7 @@ sub reinitialise { # Bit of a nasty hack to reopen connections to log files and the DB my $syslogLevel = $this->syslogLevel(); - $this->syslogLevel( NOLOG ); + $this->syslogLevel(NOLOG); $this->syslogLevel($syslogLevel) if $syslogLevel > NOLOG; my $logfileLevel = $this->fileLevel(); @@ -321,11 +321,10 @@ sub reinitialise { $this->databaseLevel(NOLOG); $this->databaseLevel($databaseLevel) if $databaseLevel > NOLOG; - my $screenLevel = $this->termLevel(); + $this->{hasTerm} = -t STDERR; + my $termLevel = $this->termLevel(); $this->termLevel(NOLOG); - $this->termLevel($screenLevel) if $screenLevel > NOLOG; - - $this->{sth} = undef; + $this->termLevel($termLevel) if $termLevel > NOLOG; } # Prevents undefined logging levels @@ -439,16 +438,13 @@ sub databaseLevel { my $databaseLevel = shift; if ( defined($databaseLevel) ) { $databaseLevel = $this->limit($databaseLevel); - if ( $this->{databaseLevel} != $databaseLevel ) { - if ( ( $databaseLevel > NOLOG ) and ( $this->{databaseLevel} <= NOLOG ) ) { - if ( ! ( $ZoneMinder::Database::dbh or ZoneMinder::Database::zmDbConnect() ) ) { - Warning("Failed connecting to db. Not using database logging."); - $this->{databaseLevel} = NOLOG; - return NOLOG; - } - } - $this->{databaseLevel} = $databaseLevel; + if ( $databaseLevel > NOLOG ) { + $this->{dbh} = ZoneMinder::Database::zmDbConnect(); + } else { + undef($this->{dbh}); } + $this->{sth} = undef; + $this->{databaseLevel} = $databaseLevel; } return $this->{databaseLevel}; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 61dfb024a..e7e3157eb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,7 +21,7 @@ target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS}) # Generate man files for the binaries destined for the bin folder FOREACH(CBINARY zma zmc zmu) - POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8) + POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8 ${ZM_MANPAGE_DEST_PREFIX}) ENDFOREACH(CBINARY zma zmc zmu) install(TARGETS zmc zma zmu RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 6da57c29e..3bf6fffae 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]; @@ -174,7 +175,7 @@ Event::Event( Error("Can't mkdir %s: %s", path, strerror(errno)); } } else { - snprintf(path, sizeof(path), "/%" PRIu64, id); + path_ptr += snprintf(path_ptr, sizeof(path), "/%" PRIu64, id); if ( mkdir(path, 0755) ) { if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); @@ -563,6 +564,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 39319e6c7..1d31addcc 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -86,6 +86,7 @@ class Event { bool videoEvent; int frames; int alarm_frames; + bool alarm_frame_written; unsigned int tot_score; unsigned int max_score; char path[PATH_MAX]; diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 4e880e1a5..2b8b4d910 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -34,15 +34,18 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs ) } else if ( level == AV_LOG_FATAL ) { // 8 log_level = Logger::FATAL; } else if ( level == AV_LOG_ERROR ) { // 16 - log_level = Logger::ERROR; + log_level = Logger::WARNING; // ffmpeg outputs a lot of errors that don't really affect anything. + //log_level = Logger::ERROR; } else if ( level == AV_LOG_WARNING ) { //24 - log_level = Logger::WARNING; - } else if ( level == AV_LOG_INFO ) { //32 log_level = Logger::INFO; - } else if ( level == AV_LOG_VERBOSE ) { //40 + //log_level = Logger::WARNING; + } else if ( level == AV_LOG_INFO ) { //32 log_level = Logger::DEBUG1; - } else if ( level == AV_LOG_DEBUG ) { //48 + //log_level = Logger::INFO; + } else if ( level == AV_LOG_VERBOSE ) { //40 log_level = Logger::DEBUG2; + } else if ( level == AV_LOG_DEBUG ) { //48 + log_level = Logger::DEBUG3; #ifdef AV_LOG_TRACE } else if ( level == AV_LOG_TRACE ) { log_level = Logger::DEBUG8; @@ -58,7 +61,6 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs ) if ( log ) { char logString[8192]; vsnprintf(logString, sizeof(logString)-1, fmt, vargs); - log->logPrint(false, __FILE__, __LINE__, log_level, logString); } } @@ -71,7 +73,10 @@ void FFMPEGInit() { av_log_set_level( AV_LOG_DEBUG ); else av_log_set_level( AV_LOG_QUIET ); - av_log_set_callback(log_libav_callback); + if ( config.log_ffmpeg ) + av_log_set_callback(log_libav_callback); + else + Info("Not enabling ffmpeg logs, as LOG_FFMPEG is disabled in options"); #if LIBAVCODEC_VERSION_CHECK(58, 18, 0, 64, 0) #else av_register_all(); diff --git a/version b/version index 00b225209..7aa332e41 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.32.3 +1.33.0 diff --git a/web/includes/Server.php b/web/includes/Server.php index aba82e79e..7424aafdf 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -62,7 +62,12 @@ class Server { if ( isset($this->{'Protocol'}) and ( $this->{'Protocol'} != '' ) ) { return $this->{'Protocol'}; } - return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http'; + + return ( + ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ) + or + ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and ( $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) ) + ) ? 'https' : 'http'; } public function Port( $new = '' ) { @@ -72,6 +77,11 @@ class Server { if ( isset($this->{'Port'}) and $this->{'Port'} ) { return $this->{'Port'}; } + + if ( isset($_SERVER['HTTP_X_FORWARDED_PORT']) ) { + return $_SERVER['HTTP_X_FORWARDED_PORT']; + } + return $_SERVER['SERVER_PORT']; } diff --git a/web/includes/actions.php b/web/includes/actions.php index b56c7ae1c..7da054017 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -474,7 +474,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) ) ); @@ -486,6 +487,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 f25b9eb15..bd80f1d89 100644 --- a/web/index.php +++ b/web/index.php @@ -169,6 +169,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 91ff87073..196c9fe89 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -201,6 +201,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' ) @@ -228,11 +245,6 @@ function getNavBarHTML($reload = null) { $running = daemonCheck(); $status = $running?translate('Running'):translate('Stopped'); ?> -