Merge branch 'release-1.34' of github.com:ZoneMinder/zoneminder into release-1.34
This commit is contained in:
commit
17369e73e2
|
@ -1,10 +1,10 @@
|
|||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
daysUntilStale: 180
|
||||
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
daysUntilClose: 30
|
||||
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
|
|
|
@ -875,7 +875,6 @@ configure_file(zmlinkcontent.sh.in "${CMAKE_CURRENT_BINARY_DIR}/zmlinkcontent.sh
|
|||
|
||||
# Create a target for man pages
|
||||
include(Pod2Man)
|
||||
ADD_MANPAGE_TARGET()
|
||||
|
||||
# Process subdirectories
|
||||
|
||||
|
|
|
@ -53,8 +53,7 @@ MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX)
|
|||
|
||||
SET(MANPAGE_TARGET "man-${MANFILE}")
|
||||
|
||||
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz)
|
||||
ADD_DEPENDENCIES(man ${MANPAGE_TARGET})
|
||||
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz)
|
||||
|
||||
INSTALL(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz
|
||||
|
|
|
@ -46,3 +46,6 @@ ZM_PATH_SWAP=@ZM_TMPDIR@
|
|||
# Full path to optional arp binary
|
||||
# ZoneMinder will find the arp binary automatically on most systems
|
||||
ZM_PATH_ARP="@ZM_PATH_ARP@"
|
||||
|
||||
#Full path to shutdown binary
|
||||
ZM_PATH_SHUTDOWN="@ZM_PATH_SHUTDOWN@"
|
||||
|
|
|
@ -476,7 +476,7 @@ CREATE TABLE `Monitors` (
|
|||
`Hue` mediumint(7) NOT NULL default '-1',
|
||||
`Colour` mediumint(7) NOT NULL default '-1',
|
||||
`EventPrefix` varchar(32) NOT NULL default 'Event-',
|
||||
`LabelFormat` varchar(64) default '%N - %y/%m/%d %H:%M:%S',
|
||||
`LabelFormat` varchar(64),
|
||||
`LabelX` smallint(5) unsigned NOT NULL default '0',
|
||||
`LabelY` smallint(5) unsigned NOT NULL default '0',
|
||||
`LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1',
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
/* This was done in 1.31.0 but zm_create.sql.in wasn't updated to match. */
|
||||
ALTER TABLE Monitors MODIFY LinkedMonitors varchar(255);
|
|
@ -0,0 +1,10 @@
|
|||
zoneminder (1.28.1-1) unstable; urgency=low
|
||||
|
||||
This version is no longer automatically initialize or upgrade database.
|
||||
See README.Debian for details.
|
||||
|
||||
Changed installation paths (please correct your web server configuration):
|
||||
/usr/share/zoneminder --> /usr/share/zoneminder/www
|
||||
/usr/lib/cgi-bin --> /usr/lib/zoneminder/cgi-bin
|
||||
|
||||
-- Dmitry Smirnov <onlyjob@debian.org> Tue, 31 Mar 2015 15:12:17 +1100
|
|
@ -0,0 +1,130 @@
|
|||
Zoneminder for Debian
|
||||
---------------------
|
||||
|
||||
Initializing database
|
||||
---------------------
|
||||
|
||||
pv /usr/share/zoneminder/db/zm_create.sql | sudo mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
OR
|
||||
cat /usr/share/zoneminder/db/zm_create.sql | sudo mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
|
||||
echo 'grant lock tables,alter,create,index,select,insert,update,delete on zm.* to 'zmuser'@localhost identified by "zmpass";'\
|
||||
| sudo mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
|
||||
Hint: generate secure password with `pwgen` and update "/etc/zm/zm.conf"
|
||||
accordingly.
|
||||
|
||||
The following command can help to ensure that zoneminder can read its
|
||||
configuration file:
|
||||
|
||||
chgrp -c www-data /etc/zm/zm.conf
|
||||
|
||||
|
||||
Upgrading database
|
||||
------------------
|
||||
|
||||
The database is updated automatically on installation. You should not need to take this step.
|
||||
|
||||
Assuming that database is on "localhost" then the following command can be
|
||||
used to upgrade "zm" database:
|
||||
|
||||
zmupdate.pl
|
||||
|
||||
Additional permissions may be required to perform upgrade:
|
||||
|
||||
echo 'grant lock tables, create, alter on zm.* to 'zmuser'@localhost identified by "zmpass";'\
|
||||
| sudo mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
|
||||
The following command prints the current version of zoneminder database:
|
||||
|
||||
echo 'select Value from Config where Name = "ZM_DYN_CURR_VERSION";' \
|
||||
| sudo mysql --defaults-file=/etc/mysql/debian.cnf --skip-column-names zm
|
||||
|
||||
|
||||
Enabling service
|
||||
----------------
|
||||
|
||||
By default Zoneminder service is not automatically started and needs to be
|
||||
manually enabled once database is configured:
|
||||
|
||||
sudo systemctl enable zoneminder.service
|
||||
|
||||
|
||||
Web server set-up
|
||||
-----------------
|
||||
|
||||
There are few manual steps to get the web interface working:
|
||||
|
||||
## Apache2
|
||||
|
||||
Apache can be configured as folder "/zm" using sample .conf:
|
||||
|
||||
sudo a2enconf zoneminder
|
||||
|
||||
Alternatively Apache web site configuration template can be used to setup
|
||||
zoneminder as "http://zoneminder":
|
||||
|
||||
sudo cp -v /usr/share/doc/zoneminder/examples/apache.conf /etc/apache2/sites-available/
|
||||
sudo a2ensite zoneminder.conf
|
||||
|
||||
Common configuration steps for Apache2:
|
||||
|
||||
sudo a2enmod cgi
|
||||
sudo service apache2 reload
|
||||
|
||||
|
||||
## nginx / fcgiwrap
|
||||
|
||||
Nginx needs "php-fpm" package to support PHP and "fcgiwrap" package
|
||||
for binary "cgi-bin" applications:
|
||||
|
||||
sudo apt-get install php-fpm fcgiwrap
|
||||
|
||||
To enable a URL alias that makes Zoneminder available from
|
||||
|
||||
http://yourserver/zm
|
||||
|
||||
the following line is to be added to "server" section of a web site
|
||||
configuration:
|
||||
|
||||
include /usr/share/doc/zoneminder/examples/nginx.conf;
|
||||
|
||||
For "default" web site it would be sufficient to include the above
|
||||
statement to the file
|
||||
|
||||
/etc/nginx/sites-enabled/default
|
||||
|
||||
To avoid problems with feeds from multiple cameras "fcgiwrap" should be
|
||||
configured to start at least as many processes as there are cameras.
|
||||
It can be done by adjusting DAEMON_OPTS in "/etc/default/fcgiwrap".
|
||||
Systemd users may be affected by the following bug:
|
||||
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=792705
|
||||
|
||||
|
||||
## Note:
|
||||
|
||||
When Zoneminder web site is running it may be necessary to set
|
||||
Options/Paths/PATH_ZMS to "/zm/cgi-bin/nph-zms" or according to chosen web
|
||||
site configuration.
|
||||
|
||||
|
||||
Changing the location for images and events
|
||||
-------------------------------------------
|
||||
|
||||
ZoneMinder is now able to be configured to use an alternative location for storing
|
||||
events and images at compile time. This package makes use of that, so symlinks in
|
||||
/usr/share/zoneminder/www are no longer necessary.
|
||||
|
||||
Access to /dev/video*
|
||||
---------------------
|
||||
|
||||
For cameras which require access to /dev/video*, zoneminder may need the
|
||||
www-data user added to the video group in order to see those cameras:
|
||||
|
||||
adduser www-data video
|
||||
|
||||
Note that all web applications running on the zoneminder server will then have
|
||||
access to all video devices on the system.
|
||||
|
||||
-- Vagrant Cascadian <vagrant@debian.org> Sun, 27 Mar 2011 13:06:56 -0700
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
## Separate substantial /usr/share into its own arch-all package.
|
||||
|
||||
## Decide how to handle database updates.
|
||||
|
||||
* Consider possibility that database may be on another machine (#469239).
|
||||
* Consider dbconfig-common? Probably not (what if database is not on localhost?).
|
||||
|
||||
### Run `zmupdate.pl` from service control scripts (init.d, service) on start?
|
||||
|
||||
Automatic upgrade will break "one DB, many zoneminders" setup (unimportant?).
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
zoneminder (1.31.39~20180223.27-stretch-1) unstable; urgency=low
|
||||
*
|
||||
-- Isaac Connor <iconnor@connortechnology.com> Fri, 23 Feb 2018 14:15:59 -0500
|
|
@ -0,0 +1,3 @@
|
|||
.gitattributes
|
||||
web/api/.gitattributes
|
||||
web/api/.gitignore
|
|
@ -0,0 +1 @@
|
|||
9
|
|
@ -0,0 +1,57 @@
|
|||
# Remember to enable cgi mod (i.e. "a2enmod cgi").
|
||||
ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
|
||||
<Directory "/usr/lib/zoneminder/cgi-bin">
|
||||
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
|
||||
# Order matters. This alias must come first.
|
||||
Alias /zm/cache /var/cache/zoneminder/cache
|
||||
<Directory /var/cache/zoneminder/cache>
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride None
|
||||
<IfModule mod_authz_core.c>
|
||||
# Apache 2.4
|
||||
Require all granted
|
||||
</IfModule>
|
||||
<IfModule !mod_authz_core.c>
|
||||
# Apache 2.2
|
||||
Order deny,allow
|
||||
Allow from all
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
Alias /zm /usr/share/zoneminder/www
|
||||
<Directory /usr/share/zoneminder/www>
|
||||
Options -Indexes +FollowSymLinks
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex index.php
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
# For better visibility, the following directives have been migrated from the
|
||||
# default .htaccess files included with the CakePHP project.
|
||||
# Parameters not set here are inherited from the parent directive above.
|
||||
<Directory "/usr/share/zoneminder/www/api">
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ app/webroot/ [L]
|
||||
RewriteRule (.*) app/webroot/$1 [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
||||
|
||||
<Directory "/usr/share/zoneminder/www/api/app">
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
||||
|
||||
<Directory "/usr/share/zoneminder/www/api/app/webroot">
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
RewriteBase /zm/api
|
||||
</Directory>
|
|
@ -0,0 +1,166 @@
|
|||
Source: zoneminder
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Isaac Connor <isaac@zoneminder.com>
|
||||
Uploaders: Isaac Connor <isaac@zoneminder.com>
|
||||
Build-Depends: debhelper, sphinx-doc, dh-linktree, dh-apache2
|
||||
,cmake
|
||||
,libx264-dev, libmp4v2-dev
|
||||
,libavdevice-dev
|
||||
,libavcodec-dev
|
||||
,libavformat-dev
|
||||
,libavutil-dev
|
||||
,libswresample-dev
|
||||
,libswscale-dev
|
||||
,ffmpeg
|
||||
,net-tools
|
||||
,libbz2-dev
|
||||
,libgcrypt20-dev
|
||||
,libcurl4-gnutls-dev
|
||||
,libturbojpeg0-dev
|
||||
,default-libmysqlclient-dev | libmysqlclient-dev | libmariadbclient-dev-compat
|
||||
,libpcre3-dev
|
||||
,libpolkit-gobject-1-dev
|
||||
,libv4l-dev [!hurd-any]
|
||||
,libvlc-dev
|
||||
,libdate-manip-perl
|
||||
,libdbd-mysql-perl
|
||||
,libphp-serialization-perl
|
||||
,libsys-mmap-perl [!hurd-any]
|
||||
,libwww-perl
|
||||
,libdata-uuid-perl
|
||||
,libssl-dev
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
# Unbundled (dh_linktree):
|
||||
,libjs-jquery
|
||||
,libjs-mootools
|
||||
Standards-Version: 3.9.8
|
||||
Homepage: http://www.zoneminder.com/
|
||||
Vcs-Browser: http://anonscm.debian.org/cgit/collab-maint/zoneminder.git
|
||||
Vcs-Git: git://anonscm.debian.org/collab-maint/zoneminder.git
|
||||
|
||||
Package: zoneminder
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
||||
,javascript-common
|
||||
,libmp4v2-2, libx264-155
|
||||
,libswscale5
|
||||
,libswresample3
|
||||
,ffmpeg
|
||||
,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
|
||||
,libdbd-mysql-perl
|
||||
,libphp-serialization-perl
|
||||
,libmodule-load-conditional-perl
|
||||
,libnet-sftp-foreign-perl
|
||||
,libarchive-zip-perl
|
||||
,libdbd-mysql-perl
|
||||
,libdevice-serialport-perl
|
||||
,libimage-info-perl
|
||||
,libjson-maybexs-perl
|
||||
,libsys-mmap-perl [!hurd-any]
|
||||
,liburi-encode-perl
|
||||
,libwww-perl, liburi-perl
|
||||
,libdata-dump-perl
|
||||
,libdatetime-perl
|
||||
,libclass-std-fast-perl
|
||||
,libsoap-wsdl-perl
|
||||
,libio-socket-multicast-perl
|
||||
,libdigest-sha-perl
|
||||
,libsys-cpu-perl, libsys-meminfo-perl
|
||||
,libdata-uuid-perl
|
||||
,libnumber-bytes-human-perl
|
||||
,libfile-slurp-perl
|
||||
,mysql-client | mariadb-client | virtual-mysql-client
|
||||
,perl-modules
|
||||
,php-mysql, php-gd, php-apcu, php-apc | php-apcu-bc, php-json
|
||||
,policykit-1
|
||||
,rsyslog | system-log-daemon
|
||||
,zip
|
||||
,libpcre3
|
||||
,libcrypt-eksblowfish-perl
|
||||
,libdata-entropy-perl
|
||||
Recommends: ${misc:Recommends}
|
||||
,libapache2-mod-php | php-fpm
|
||||
,mysql-server | mariadb-server | virtual-mysql-server
|
||||
,zoneminder-doc (>= ${source:Version})
|
||||
,ffmpeg
|
||||
Suggests: fcgiwrap, logrotate
|
||||
Description: video camera security and surveillance solution
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
||||
applications, including commercial or home CCTV, theft prevention and child
|
||||
or family member or home monitoring and other care scenarios. It
|
||||
supports capture, analysis, recording, and monitoring of video data coming
|
||||
from one or more video or network cameras attached to a Linux system.
|
||||
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
cameras using a variety of protocols. It is suitable for use as a home
|
||||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
|
||||
#Package: libzoneminder-perl
|
||||
#Section: perl
|
||||
#Architecture: all
|
||||
#Multi-Arch: foreign
|
||||
#Depends: ${misc:Depends}, ${perl:Depends}
|
||||
# ,libarchive-zip-perl
|
||||
# ,libdbd-mysql-perl
|
||||
# ,libdevice-serialport-perl
|
||||
# ,libimage-info-perl
|
||||
# ,libjson-maybexs-perl
|
||||
# ,libsys-mmap-perl [!hurd-any]
|
||||
# ,liburi-encode-perl
|
||||
# ,libwww-perl
|
||||
#Description: ZoneMinder Perl libraries
|
||||
# ZoneMinder is intended for use in single or multi-camera video security
|
||||
# applications, including commercial or home CCTV, theft prevention and child
|
||||
# or family member or home monitoring and other care scenarios. It
|
||||
# supports capture, analysis, recording, and monitoring of video data coming
|
||||
# from one or more video or network cameras attached to a Linux system.
|
||||
# ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
# cameras using a variety of protocols. It is suitable for use as a home
|
||||
# video security system and for commercial or professional video security
|
||||
# and surveillance. It can also be integrated into a home automation system
|
||||
# via X.10 or other protocols.
|
||||
# .
|
||||
# This package provides ZoneMinder Perl libraries; it can be used to
|
||||
# write custom interfaces as well.
|
||||
|
||||
Package: zoneminder-doc
|
||||
Section: doc
|
||||
Architecture: all
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends}, ${sphinxdoc:Depends}, python-sphinx-rtd-theme | python3-sphinx-rtd-theme
|
||||
Suggests: www-browser
|
||||
Description: ZoneMinder documentation
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
||||
applications, including commercial or home CCTV, theft prevention and child
|
||||
or family member or home monitoring and other care scenarios. It
|
||||
supports capture, analysis, recording, and monitoring of video data coming
|
||||
from one or more video or network cameras attached to a Linux system.
|
||||
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
cameras using a variety of protocols. It is suitable for use as a home
|
||||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
.
|
||||
This package provides ZoneMinder documentation in HTML format.
|
||||
|
||||
Package: zoneminder-dbg
|
||||
Section: debug
|
||||
Priority: extra
|
||||
Architecture: any
|
||||
Depends: zoneminder (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Zoneminder -- debugging symbols
|
||||
ZoneMinder is intended for use in single or multi-camera video security
|
||||
applications, including commercial or home CCTV, theft prevention and child
|
||||
or family member or home monitoring and other care scenarios. It
|
||||
supports capture, analysis, recording, and monitoring of video data coming
|
||||
from one or more video or network cameras attached to a Linux system.
|
||||
ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
|
||||
cameras using a variety of protocols. It is suitable for use as a home
|
||||
video security system and for commercial or professional video security
|
||||
and surveillance. It can also be integrated into a home automation system
|
||||
via X.10 or other protocols.
|
||||
.
|
||||
This package provides debugging symbols
|
|
@ -0,0 +1,174 @@
|
|||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: ZoneMinder
|
||||
Upstream-Contact: Philip Coombes <philip.coombes@zoneminder.com>
|
||||
Source: https://github.com/ZoneMinder/ZoneMinder
|
||||
Comment:
|
||||
This package was originally debianized by matrix <matrix@cecilia>
|
||||
on Mon, 7 Mar 2005 02:07:57 -0500.
|
||||
It was re-done for submission to the Debian project by Peter Howard
|
||||
<pjh@northern-ridge.com.au> on Fri, 8 Dec 2006 10:19:43 +1100
|
||||
Files-Excluded:
|
||||
web/skins/*/js/jquery-*
|
||||
web/tools/mootools/*-yc.js
|
||||
|
||||
Files: *
|
||||
Copyright: 2001-2014 Philip Coombes <philip.coombes@zoneminder.com>
|
||||
2008 Brian Rudy <brudyNO@SPAMpraecogito.com>
|
||||
2014 Vincent Giovannone
|
||||
2013 Tim Craig <timcraigNO@SPAMsonic.net>
|
||||
2003-2008 Corey DeLasaux
|
||||
2001-2010 Chris Kistner
|
||||
License: GPL-2+
|
||||
|
||||
Files: distros/*
|
||||
Copyright: 2001-2008 Philip Coombes <philip.coombes@zoneminder.com>
|
||||
2014 Isaac Connor <iconnor@connortechnology.com>
|
||||
2005 Serg Oskin
|
||||
License: GPL-2+
|
||||
|
||||
Files: web/skins/*/js/jquery-*
|
||||
Copyright: 2010 John Resig
|
||||
2010 The Dojo Foundation
|
||||
License: GPL-2 or Expat
|
||||
Comment:
|
||||
Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
http://jquery.org/license
|
||||
.
|
||||
Includes Sizzle.js http://sizzlejs.com/
|
||||
Released under the MIT, BSD, and GPL Licenses.
|
||||
|
||||
Files: web/tools/mootools/*.js
|
||||
Copyright: 2009 Marcelo Jorge Vieira (metal) <metal@alucinados.com>
|
||||
2006-2010 Valerio Proietti (http://mad4milk.net/)
|
||||
License: Expat
|
||||
|
||||
Files: web/api/*
|
||||
Copyright: 2005-2013 Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
License: Expat
|
||||
|
||||
Files:
|
||||
cmake/Modules/CheckPrototypeDefinition*.cmake
|
||||
cmake/Modules/FindGLIB2.cmake
|
||||
cmake/Modules/FindPolkit.cmake
|
||||
cmake/Modules/GNUInstallDirs.cmake
|
||||
Copyright:
|
||||
2005-2011 Kitware, Inc.
|
||||
2010-2011 Andreas Schneider <asn@cryptomilk.org>
|
||||
2009 Dario Freddi <drf@kde.org>
|
||||
2008 Laurent Montel, <montel@kde.org>
|
||||
2011 Nikita Krupen'ko <krnekit@gmail.com>
|
||||
License: BSD-3-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
.
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
.
|
||||
* The names of Kitware, Inc., the Insight Consortium, or the names of
|
||||
any consortium members, or of any contributors, may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Files: cmake/Modules/FindPerlModules.cmake
|
||||
Copyright: 2012 Iowa State University
|
||||
License: Boost-1.0
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
.
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
.
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2015 Dmitry Smirnov <onlyjob@debian.org>
|
||||
2007-2014 Peter Howard <pjh@northern-ridge.com.au>
|
||||
2010-2012 Vagrant Cascadian <vagrant@debian.org>
|
||||
2001-2008 Philip Coombes <philip.coombes@zoneminder.com>
|
||||
License: GPL-2+
|
||||
|
||||
License: Expat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
License: GPL-2+
|
||||
This package 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 package 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 package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
.
|
||||
The complete text of the GNU General Public License version 2
|
||||
can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
License: GPL-2
|
||||
This package 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; version 2 of the License.
|
||||
.
|
||||
This package 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 package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
.
|
||||
The complete text of the GNU General Public License version 2
|
||||
can be found in "/usr/share/common-licenses/GPL-2".
|
|
@ -0,0 +1,32 @@
|
|||
location /zm/cgi-bin {
|
||||
gzip off;
|
||||
alias /usr/lib/zoneminder/cgi-bin;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
fastcgi_pass unix:/var/run/fcgiwrap.socket;
|
||||
}
|
||||
|
||||
location /zm {
|
||||
# if ($scheme ~ ^http:){
|
||||
# rewrite ^(.*)$ https://$host$1 permanent;
|
||||
# }
|
||||
|
||||
gzip off;
|
||||
alias /usr/share/zoneminder/www;
|
||||
index index.php;
|
||||
|
||||
location ~ \.php$ {
|
||||
if (!-f $request_filename) { return 404; }
|
||||
expires epoch;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||
}
|
||||
|
||||
location ~ \.(jpg|jpeg|gif|png|ico)$ {
|
||||
access_log off;
|
||||
expires 33d;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
[dch]
|
||||
id-length = 0
|
||||
|
||||
[import-orig]
|
||||
pristine-tar = False
|
||||
merge = False
|
|
@ -0,0 +1,2 @@
|
|||
usr/share/man/man3
|
||||
usr/share/perl5
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_LDFLAGS_MAINT_APPEND += -Wl,--as-needed
|
||||
|
||||
ifeq ($(DEB_BUILD_ARCH_OS),hurd)
|
||||
ARGS:= -DZM_NO_MMAP=ON
|
||||
endif
|
||||
|
||||
%:
|
||||
dh $@ --parallel --buildsystem=cmake --builddirectory=dbuild \
|
||||
--with sphinxdoc,apache2,linktree
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- $(ARGS) \
|
||||
-DCMAKE_VERBOSE_MAKEFILE=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DZM_CONFIG_DIR="/etc/zm" \
|
||||
-DZM_CONFIG_SUBDIR="/etc/zm/conf.d" \
|
||||
-DZM_RUNDIR="/run/zm" \
|
||||
-DZM_SOCKDIR="/run/zm" \
|
||||
-DZM_TMPDIR="/tmp/zm" \
|
||||
-DZM_CGIDIR="/usr/lib/zoneminder/cgi-bin" \
|
||||
-DZM_CACHEDIR="/var/cache/zoneminder/cache" \
|
||||
-DZM_DIR_EVENTS="/var/cache/zoneminder/events" \
|
||||
-DZM_PATH_SHUTDOWN="/sbin/shutdown" \
|
||||
-DZM_PATH_ZMS="/zm/cgi-bin/nph-zms"
|
||||
|
||||
override_dh_clean:
|
||||
dh_clean $(MANPAGES1)
|
||||
$(RM) -r docs/_build
|
||||
|
||||
build-indep:
|
||||
#$(MAKE) -C docs text
|
||||
$(MAKE) -C docs html
|
||||
|
||||
MANPAGES1 = dbuild/scripts/zmupdate.pl.1
|
||||
$(MANPAGES1):
|
||||
# generate man page(s):
|
||||
pod2man -s1 --stderr --utf8 $(patsubst %.1, %, $@) $@
|
||||
|
||||
## reproducible build:
|
||||
LAST_CHANGE=$(shell dpkg-parsechangelog -S Date)
|
||||
BUILD_DATE=$(shell LC_ALL=C date -u "+%B %d, %Y" -d "$(LAST_CHANGE)")
|
||||
override_dh_installman: $(MANPAGES1)
|
||||
$(MAKE) -C docs man SPHINXOPTS="-D today=\"$(BUILD_DATE)\""
|
||||
dh_installman --language=C $(MANPAGES1)
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install --destdir=$(CURDIR)/debian/tmp
|
||||
# remove worthless files:
|
||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/perl5/*/*/*/.packlist
|
||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/perl5/*/*.in
|
||||
# remove empty directories:
|
||||
find $(CURDIR)/debian/tmp/usr -type d -empty -delete -printf 'removed %p\n'
|
||||
# remove extra-license-file:
|
||||
$(RM) -v $(CURDIR)/debian/tmp/usr/share/zoneminder/www/api/lib/Cake/LICENSE.txt
|
||||
|
||||
override_dh_fixperms:
|
||||
dh_fixperms
|
||||
#
|
||||
# As requested by the Debian Webapps Policy Manual §3.2.1
|
||||
chown root:www-data $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
chmod 640 $(CURDIR)/debian/zoneminder/etc/zm/zm.conf
|
||||
|
||||
override_dh_strip:
|
||||
[ -d "$(CURDIR)/debian/zoneminder-dbg" ] \
|
||||
&& dh_strip --dbg-package=zoneminder-dbg \
|
||||
|| dh_strip
|
||||
|
||||
#%:
|
||||
# dh $@ --parallel --buildsystem=autoconf --with autoreconf
|
||||
#
|
||||
#override_dh_auto_configure:
|
||||
# dh_auto_configure -- \
|
||||
# --sysconfdir=/etc/zm \
|
||||
# --with-mysql=/usr \
|
||||
# --with-webdir=/usr/share/zoneminder \
|
||||
# --with-ffmpeg=/usr \
|
||||
# --with-cgidir=/usr/lib/cgi-bin \
|
||||
# --with-webuser=www-data \
|
||||
# --with-webgroup=www-data \
|
||||
# --enable-mmap=yes
|
|
@ -0,0 +1 @@
|
|||
3.0 (quilt)
|
|
@ -0,0 +1,9 @@
|
|||
## Actually sources are there: "*-nc.js".
|
||||
source-is-missing web/tools/mootools/mootools-*-yc.js
|
||||
|
||||
## We're using "libjs-jquery" instead.
|
||||
source-is-missing web/skins/*/js/jquery-1.4.2.min.js
|
||||
|
||||
## Acknowledged, will repack eventually.
|
||||
source-contains-prebuilt-javascript-object web/tools/mootools/mootools-*-yc.js
|
||||
source-contains-prebuilt-javascript-object web/skins/*/js/jquery-1.4.2.min.js
|
|
@ -0,0 +1,8 @@
|
|||
Document: zoneminder-doc
|
||||
Title: Zoneminder documentation
|
||||
Abstract: This document describes how to use Zoneminder.
|
||||
Section: System/Administration
|
||||
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/zoneminder-doc/html/index.html
|
||||
Files: /usr/share/doc/zoneminder-doc/html/*
|
|
@ -0,0 +1 @@
|
|||
docs/_build/html usr/share/doc/zoneminder-doc/
|
|
@ -0,0 +1,2 @@
|
|||
## Convenience symlink:
|
||||
/usr/share/doc/zoneminder-doc/html /usr/share/doc/zoneminder/html
|
|
@ -0,0 +1 @@
|
|||
conf debian/conf/apache2/zoneminder.conf nginx
|
|
@ -0,0 +1,5 @@
|
|||
Unless bug is specific to Debian please consider reporting it directly to
|
||||
upstream developer(s):
|
||||
|
||||
https://github.com/ZoneMinder/ZoneMinder/issues
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
var/log/zm
|
||||
var/lib/zm
|
||||
var/cache/zoneminder/events
|
||||
var/cache/zoneminder/images
|
||||
var/cache/zoneminder/temp
|
||||
var/cache/zoneminder/cache
|
||||
usr/share/zoneminder/db
|
||||
etc/zm/
|
||||
etc/zm/conf.d
|
|
@ -0,0 +1 @@
|
|||
README.md
|
|
@ -0,0 +1,2 @@
|
|||
debian/examples/*
|
||||
dbuild/misc/apache.conf
|
|
@ -0,0 +1,91 @@
|
|||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: zoneminder
|
||||
# Required-Start: $network $remote_fs $syslog
|
||||
# Required-Stop: $network $remote_fs $syslog
|
||||
# Should-Start: mysql
|
||||
# Should-Stop: mysql
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Control ZoneMinder as a Service
|
||||
# Description: ZoneMinder CCTV recording and surveillance system
|
||||
### END INIT INFO
|
||||
# chkconfig: 2345 20 20
|
||||
|
||||
# Source function library.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
prog=ZoneMinder
|
||||
ZM_PATH_BIN="/usr/bin"
|
||||
RUNDIR="/run/zm"
|
||||
TMPDIR="/tmp/zm"
|
||||
command="$ZM_PATH_BIN/zmpkg.pl"
|
||||
|
||||
start() {
|
||||
echo -n "Starting $prog: "
|
||||
export TZ=:/etc/localtime
|
||||
mkdir -p "$RUNDIR" && chown www-data:www-data "$RUNDIR"
|
||||
mkdir -p "$TMPDIR" && chown www-data:www-data "$TMPDIR"
|
||||
$command start
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && echo success
|
||||
[ $RETVAL != 0 ] && echo failure
|
||||
echo
|
||||
[ $RETVAL = 0 ] && touch /var/lock/zm
|
||||
return $RETVAL
|
||||
}
|
||||
stop() {
|
||||
echo -n "Stopping $prog: "
|
||||
#
|
||||
# Why is this status check being done?
|
||||
# as $command stop returns 1 if zoneminder
|
||||
# is stopped, which will result in
|
||||
# this returning 1, which will stuff
|
||||
# dpkg when it tries to stop zoneminder before
|
||||
# uninstalling . . .
|
||||
#
|
||||
result=`$command status`
|
||||
if [ ! "$result" = "running" ]; then
|
||||
echo "Zoneminder already stopped"
|
||||
echo
|
||||
RETVAL=0
|
||||
else
|
||||
$command stop
|
||||
RETVAL=$?
|
||||
[ $RETVAL = 0 ] && echo success
|
||||
[ $RETVAL != 0 ] && echo failure
|
||||
echo
|
||||
[ $RETVAL = 0 ] && rm -f /var/lock/zm
|
||||
fi
|
||||
}
|
||||
status() {
|
||||
result=`$command status`
|
||||
if [ "$result" = "running" ]; then
|
||||
echo "ZoneMinder is running"
|
||||
RETVAL=0
|
||||
else
|
||||
echo "ZoneMinder is stopped"
|
||||
RETVAL=1
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'start')
|
||||
start
|
||||
;;
|
||||
'stop')
|
||||
stop
|
||||
;;
|
||||
'restart' | 'force-reload')
|
||||
stop
|
||||
start
|
||||
;;
|
||||
'status')
|
||||
status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 { start | stop | restart | status }"
|
||||
RETVAL=1
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
|
@ -0,0 +1,11 @@
|
|||
etc/zm/zm.conf
|
||||
etc/zm/conf.d/*
|
||||
usr/bin
|
||||
usr/lib/zoneminder
|
||||
usr/share/polkit-1
|
||||
usr/share/zoneminder/db
|
||||
usr/share/zoneminder/www
|
||||
|
||||
# libzoneminder-perl files:
|
||||
usr/share/man/man3
|
||||
usr/share/perl5
|
|
@ -0,0 +1 @@
|
|||
/var/tmp /usr/share/zoneminder/www/api/app/tmp
|
|
@ -0,0 +1,14 @@
|
|||
## cakephp
|
||||
#replace /usr/share/php/Cake /usr/share/zoneminder/www/api/lib/Cake
|
||||
|
||||
## libjs-mootools
|
||||
replace /usr/share/javascript/mootools/mootools.js /usr/share/zoneminder/www/tools/mootools/mootools-core.js
|
||||
replace /usr/share/javascript/mootools/mootools.js /usr/share/zoneminder/www/tools/mootools/mootools-core-1.3.2-nc.js
|
||||
replace /usr/share/javascript/mootools/mootools.js /usr/share/zoneminder/www/tools/mootools/mootools-core-1.3.2-yc.js
|
||||
replace /usr/share/javascript/mootools/mootools-more.js /usr/share/zoneminder/www/tools/mootools/mootools-more.js
|
||||
replace /usr/share/javascript/mootools/mootools-more.js /usr/share/zoneminder/www/tools/mootools/mootools-more-1.3.2.1-nc.js
|
||||
replace /usr/share/javascript/mootools/mootools-more.js /usr/share/zoneminder/www/tools/mootools/mootools-more-1.3.2.1-yc.js
|
||||
|
||||
## libjs-jquery
|
||||
replace /usr/share/javascript/jquery/jquery.min.js /usr/share/zoneminder/www/skins/classic/js/jquery-1.4.2.min.js
|
||||
replace /usr/share/javascript/jquery/jquery.min.js /usr/share/zoneminder/www/skins/flat/js/jquery-1.4.2.min.js
|
|
@ -0,0 +1,14 @@
|
|||
# Depends: policykit-1
|
||||
unusual-interpreter usr/bin/zmsystemctl.pl #!/usr/bin/pkexec
|
||||
|
||||
# Intentionally not others-readable, #637685.
|
||||
non-standard-file-perm etc/zm/zm.conf 0640 != 0644
|
||||
|
||||
# Bundled Cake PHP framework, not intended for direct execution:
|
||||
script-not-executable usr/share/zoneminder/www/api/*
|
||||
|
||||
# Annoying but seems to be too much troubles to fix; should be fixed upstream:
|
||||
script-with-language-extension usr/bin/*.pl
|
||||
|
||||
# dh-linktree:
|
||||
package-contains-broken-symlink usr/share/zoneminder/www/api/lib/Cake/*
|
|
@ -0,0 +1,13 @@
|
|||
/var/log/zm/*.log {
|
||||
missingok
|
||||
notifempty
|
||||
sharedscripts
|
||||
delaycompress
|
||||
compress
|
||||
postrotate
|
||||
/usr/bin/zmpkg.pl logrot >>/dev/null 2>&1 || :
|
||||
endscript
|
||||
daily
|
||||
rotate 7
|
||||
maxage 7
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
rm_conffile /etc/zm/apache.conf 1.28.1-5~
|
|
@ -0,0 +1 @@
|
|||
docs/_build/man/*.1
|
|
@ -0,0 +1,66 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = "configure" ]; then
|
||||
|
||||
. /etc/zm/zm.conf
|
||||
for i in /etc/zm/conf.d/*.conf; do
|
||||
. $i
|
||||
done;
|
||||
|
||||
|
||||
# The logs can contain passwords, etc... so by setting group root, only www-data can read them, not people in the www-data group
|
||||
chown www-data:root /var/log/zm
|
||||
chown www-data:www-data /var/lib/zm
|
||||
if [ -z "$2" ]; then
|
||||
chown www-data:www-data /var/cache/zoneminder /var/cache/zoneminder/*
|
||||
fi
|
||||
|
||||
# Do this every time the package is installed or upgraded
|
||||
# Ensure zoneminder is stopped
|
||||
invoke-rc.d zoneminder stop || true
|
||||
|
||||
if [ "$ZM_DB_HOST" = "localhost" ]; then
|
||||
if [ -e "/etc/init.d/mysql" ]; then
|
||||
#
|
||||
# Get mysql started if it isn't
|
||||
#
|
||||
if ! $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
invoke-rc.d mysql start
|
||||
fi
|
||||
if $(/etc/init.d/mysql status >/dev/null 2>&1); then
|
||||
mysqladmin --defaults-file=/etc/mysql/debian.cnf -f reload
|
||||
# test if database if already present...
|
||||
if ! $(echo quit | mysql --defaults-file=/etc/mysql/debian.cnf zm > /dev/null 2> /dev/null) ; then
|
||||
cat /usr/share/zoneminder/db/zm_create.sql | mysql --defaults-file=/etc/mysql/debian.cnf
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error creating db."
|
||||
exit 1;
|
||||
fi
|
||||
# This creates the user.
|
||||
echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost identified by \"${ZM_DB_PASS}\";" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
else
|
||||
echo "grant lock tables, alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on ${ZM_DB_NAME}.* to '${ZM_DB_USER}'@localhost;" | mysql --defaults-file=/etc/mysql/debian.cnf mysql
|
||||
fi
|
||||
|
||||
zmupdate.pl --nointeractive
|
||||
zmupdate.pl --nointeractive -f
|
||||
|
||||
# Add any new PTZ control configurations to the database (will not overwrite)
|
||||
zmcamtool.pl --import >/dev/null 2>&1
|
||||
|
||||
else
|
||||
echo 'NOTE: mysql not running, please start mysql and run dpkg-reconfigure zoneminder when it is running.'
|
||||
fi
|
||||
else
|
||||
echo 'mysql not found, assuming remote server.'
|
||||
fi
|
||||
else
|
||||
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
|
||||
fi
|
||||
echo "Done Updating, starting ZoneMinder"
|
||||
invoke-rc.d zoneminder start || true
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
|
@ -0,0 +1,14 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = "purge" ]; then
|
||||
echo "
|
||||
Reminder: to completely remove \"zoneminder\" it may be necessary
|
||||
* to delete database using the following sample command:
|
||||
sudo mysqladmin --defaults-file=/etc/mysql/debian.cnf -f drop zm
|
||||
* to delete remaining data files in "/var/cache/zoneminder".
|
||||
"
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
## Remove obsolete symlink which is in the way of dh_apache2:
|
||||
ol="/etc/apache2/conf-available/zoneminder.conf"
|
||||
if [ -h "${ol}" ]; then
|
||||
[ "$(readlink ${ol})" = "/etc/zm/apache.conf" ] && rm -f "${ol}"
|
||||
fi
|
||||
|
||||
#DEBHELPER#
|
|
@ -0,0 +1,4 @@
|
|||
d /run/zm 0755 www-data www-data
|
||||
d /tmp/zm 0755 www-data www-data
|
||||
d /var/tmp/zm 0755 www-data www-data
|
||||
d /var/cache/zoneminder/cache 0755 www-data www-data
|
|
@ -28,7 +28,7 @@
|
|||
%global _hardened_build 1
|
||||
|
||||
Name: zoneminder
|
||||
Version: 1.34.14
|
||||
Version: 1.34.20
|
||||
Release: 1%{?dist}
|
||||
Summary: A camera monitoring and analysis tool
|
||||
Group: System Environment/Daemons
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
zoneminder (1.31.39~20180223.27-stretch-1) unstable; urgency=low
|
||||
*
|
||||
-- Isaac Connor <iconnor@connortechnology.com> Fri, 23 Feb 2018 14:15:59 -0500
|
||||
zoneminder (1.35.6~20200825.27-xenial) xenial; urgency=low
|
||||
*
|
||||
-- Isaac Connor <isaac@zoneminder.com> Tue, 25 Aug 2020 09:28:18 -0400
|
||||
|
|
|
@ -29,7 +29,7 @@ configure_file(zm.in "${CMAKE_CURRENT_BINARY_DIR}/zm" @ONLY)
|
|||
#configure_file(zmeventdump.in zmeventdump @ONLY)
|
||||
|
||||
# Generate man files for the perl scripts destined for the bin folder
|
||||
file(GLOB perlscripts "*.pl")
|
||||
file(GLOB perlscripts "${CMAKE_CURRENT_BINARY_DIR}/*.pl")
|
||||
FOREACH(PERLSCRIPT ${perlscripts})
|
||||
get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME)
|
||||
POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX})
|
||||
|
|
|
@ -69,9 +69,9 @@ sub sendCmd {
|
|||
|
||||
my $result = undef;
|
||||
|
||||
printMsg($cmd, 'Tx');
|
||||
$self->printMsg($cmd, 'Tx');
|
||||
|
||||
my $req = HTTP::Request->new( POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi" );
|
||||
my $req = HTTP::Request->new(POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi");
|
||||
$req->content($cmd);
|
||||
my $res = $self->{ua}->request($req);
|
||||
|
||||
|
|
|
@ -143,10 +143,10 @@ sub PutCmd {
|
|||
} else {
|
||||
Info('Missing username and password in Control Address.');
|
||||
}
|
||||
Fatal($res->status_line);
|
||||
Error($res->status_line);
|
||||
}
|
||||
} else {
|
||||
Fatal($res->status_line);
|
||||
Error($res->status_line);
|
||||
}
|
||||
} # end unless res->is_success
|
||||
} # end sub putCmd
|
||||
|
|
|
@ -49,9 +49,9 @@ my %options;
|
|||
GetOptions(
|
||||
'id=i' =>\$id,
|
||||
'command=s' =>\$options{command},
|
||||
'xcoord=i' =>\$options{xcoord},
|
||||
'ycoord=i' =>\$options{ycoord},
|
||||
'speed=i' =>\$options{speed},
|
||||
'xcoord=f' =>\$options{xcoord},
|
||||
'ycoord=f' =>\$options{ycoord},
|
||||
'speed=f' =>\$options{speed},
|
||||
'step=i' =>\$options{step},
|
||||
'panspeed=i' =>\$options{panspeed},
|
||||
'tiltspeed=i' =>\$options{tiltspeed},
|
||||
|
|
|
@ -160,7 +160,7 @@ if ( !$server_up ) {
|
|||
use ZoneMinder::Server qw(CpuLoad);
|
||||
if ( ! defined $dbh->do(q{UPDATE Servers SET Status=?,TotalMem=?,FreeMem=?,TotalSwap=?,FreeSwap=? WHERE Id=?}, undef,
|
||||
'NotRunning', &totalmem, &freemem, &totalswap, &freeswap, $Config{ZM_SERVER_ID} ) ) {
|
||||
Error("Failed Updating status of Server record to Not RUnning for Id=$Config{ZM_SERVER_ID}" . $dbh->errstr());
|
||||
Error('Failed Updating status of Server record to Not Running for Id='.$Config{ZM_SERVER_ID}.': '.$dbh->errstr());
|
||||
}
|
||||
}
|
||||
# Server is not up. Some commands can still be handled
|
||||
|
@ -173,7 +173,7 @@ if ( !$server_up ) {
|
|||
print("stopped\n");
|
||||
exit();
|
||||
} elsif ( $command ne 'startup' ) {
|
||||
print('Unable to connect to server using socket at ' . SOCK_FILE . "\n");
|
||||
print('Unable to connect to server using socket at '.SOCK_FILE."\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
@ -189,10 +189,10 @@ if ( !$server_up ) {
|
|||
|
||||
socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
|
||||
my $attempts = 0;
|
||||
while( !connect(CLIENT, $saddr) ) {
|
||||
while ( !connect(CLIENT, $saddr) ) {
|
||||
$attempts++;
|
||||
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.", attempt $attempts");
|
||||
Fatal("Can't connect: $!") if $attempts > MAX_CONNECT_DELAY;
|
||||
Debug('Waiting for zmdc.pl server process at '.SOCK_FILE.', attempt '.$attempts);
|
||||
Fatal('Can\'t connect to zmdc.pl server process at '.SOCK_FILE.': '.$!) if $attempts > MAX_CONNECT_DELAY;
|
||||
usleep(200000);
|
||||
} # end while
|
||||
} elsif ( defined($cpid) ) {
|
||||
|
@ -255,13 +255,13 @@ sub run {
|
|||
close($PID);
|
||||
} else {
|
||||
# Log not initialized at this point so use die instead
|
||||
die "Can't open pid file at ".ZM_PID."\n";
|
||||
die 'Can\'t open pid file at '.ZM_PID."\n";
|
||||
}
|
||||
|
||||
my $fd = 0;
|
||||
|
||||
# This also closes dbh and CLIENT and SERVER
|
||||
while( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
|
||||
while ( $fd < POSIX::sysconf(&POSIX::_SC_OPEN_MAX) ) {
|
||||
POSIX::close($fd++);
|
||||
}
|
||||
|
||||
|
@ -301,13 +301,14 @@ sub run {
|
|||
my $timeout = 1;
|
||||
my $secs_count = 0;
|
||||
|
||||
while( !$zm_terminate ) {
|
||||
while ( !$zm_terminate ) {
|
||||
|
||||
if ( $Config{ZM_SERVER_ID} ) {
|
||||
if ( ! ( $secs_count % 60 ) ) {
|
||||
while ( (!$zm_terminate) and !($dbh and $dbh->ping()) ) {
|
||||
Warning("Not connected to db ($dbh)".($dbh?' ping('.$dbh->ping().')':''). ($DBI::errstr?" errstr($DBI::errstr)":'').' Reconnecting');
|
||||
$dbh = zmDbConnect();
|
||||
sleep 10 if !$dbh;
|
||||
}
|
||||
last if $zm_terminate;
|
||||
|
||||
|
|
|
@ -48,6 +48,49 @@ while( 1 ) {
|
|||
$dbh->do('DELETE FROM Events_Week WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 week)') or Error($dbh->errstr());
|
||||
$dbh->do('DELETE FROM Events_Month WHERE StartTime < DATE_SUB(NOW(), INTERVAL 1 month)') or Error($dbh->errstr());
|
||||
|
||||
# Prune the Logs table if required
|
||||
if ( $Config{ZM_LOG_DATABASE_LIMIT} ) {
|
||||
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^\d+$/ ) {
|
||||
# Number of rows
|
||||
my $selectLogRowCountSql = 'SELECT count(*) AS `Rows` FROM `Logs`';
|
||||
my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql )
|
||||
or Fatal("Can't prepare '$selectLogRowCountSql': ".$dbh->errstr());
|
||||
my $res = $selectLogRowCountSth->execute()
|
||||
or Fatal("Can't execute: ".$selectLogRowCountSth->errstr());
|
||||
my $row = $selectLogRowCountSth->fetchrow_hashref();
|
||||
my $logRows = $row->{Rows};
|
||||
if ( $logRows > $Config{ZM_LOG_DATABASE_LIMIT} ) {
|
||||
my $deleteLogByRowsSql = 'DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?';
|
||||
my $deleteLogByRowsSth = $dbh->prepare_cached( $deleteLogByRowsSql )
|
||||
or Fatal("Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr());
|
||||
$res = $deleteLogByRowsSth->execute( $logRows - $Config{ZM_LOG_DATABASE_LIMIT} )
|
||||
or Fatal("Can't execute: ".$deleteLogByRowsSth->errstr());
|
||||
if ( $deleteLogByRowsSth->rows() ) {
|
||||
Debug('Deleted '.$deleteLogByRowsSth->rows().' log table entries by count');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Time of record
|
||||
|
||||
# 7 days is invalid. We need to remove the s
|
||||
if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^(.*)s$/ ) {
|
||||
$Config{ZM_LOG_DATABASE_LIMIT} = $1;
|
||||
}
|
||||
my $deleted_rows;
|
||||
do {
|
||||
my $deleteLogByTimeSql =
|
||||
'DELETE FROM `Logs`
|
||||
WHERE `TimeKey` < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 100';
|
||||
my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql )
|
||||
or Fatal("Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr());
|
||||
my $res = $deleteLogByTimeSth->execute()
|
||||
or Fatal("Can't execute: ".$deleteLogByTimeSth->errstr());
|
||||
$deleted_rows = $deleteLogByTimeSth->rows();
|
||||
Debug("Deleted $deleted_rows log table entries by time");
|
||||
} while ( $deleted_rows );
|
||||
}
|
||||
} # end if ZM_LOG_DATABASE_LIMIT
|
||||
|
||||
sleep($Config{ZM_STATS_UPDATE_INTERVAL});
|
||||
} # end while (1)
|
||||
|
||||
|
|
|
@ -119,7 +119,6 @@ if ( !$monitor->{CanMoveMap} ) {
|
|||
}
|
||||
}
|
||||
|
||||
Debug("Found monitor for id '$monitor'");
|
||||
exit(-1) if !zmMemVerify($monitor);
|
||||
|
||||
sub Suspend {
|
||||
|
|
|
@ -121,6 +121,8 @@ GetOptions(
|
|||
my $dbh = zmDbConnect(undef, { mysql_multi_statements=>1 } );
|
||||
$Config{ZM_DB_USER} = $dbUser;
|
||||
$Config{ZM_DB_PASS} = $dbPass;
|
||||
# we escape dbpass with single quotes so that $ in the password has no effect, but dbpass could have a ' in it.
|
||||
$dbPass =~ s/'/\\'/g;
|
||||
|
||||
if ( ! ($check || $freshen || $rename || $zoneFix || $migrateEvents || $version) ) {
|
||||
if ( $Config{ZM_DYN_DB_VERSION} ) {
|
||||
|
@ -384,21 +386,22 @@ if ( $version ) {
|
|||
my $command = 'mysqldump';
|
||||
if ( defined($portOrSocket) ) {
|
||||
if ( $portOrSocket =~ /^\// ) {
|
||||
$command .= " -S".$portOrSocket;
|
||||
$command .= ' -S'.$portOrSocket;
|
||||
} else {
|
||||
$command .= " -h".$host." -P".$portOrSocket;
|
||||
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||
}
|
||||
} else {
|
||||
$command .= " -h".$host;
|
||||
$command .= ' -h'.$host;
|
||||
}
|
||||
if ( $dbUser ) {
|
||||
$command .= ' -u'.$dbUser;
|
||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
||||
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||
}
|
||||
my $backup = "@ZM_TMPDIR@/".$Config{ZM_DB_NAME}."-".$version.".dump";
|
||||
$command .= " --add-drop-table --databases ".$Config{ZM_DB_NAME}." > ".$backup;
|
||||
print( "Creating backup to $backup. This may take several minutes.\n" );
|
||||
print( "Executing '$command'\n" ) if ( logDebugging() );
|
||||
my $backup = '@ZM_TMPDIR@/'.$Config{ZM_DB_NAME}.'-'.$version.'.dump';
|
||||
$command .= ' --add-drop-table --databases '.$Config{ZM_DB_NAME}.' > '.$backup;
|
||||
print("Creating backup to $backup. This may take several minutes.\n");
|
||||
($command) = $command =~ /(.*)/; # detaint
|
||||
print("Executing '$command'\n") if logDebugging();
|
||||
my $output = qx($command);
|
||||
my $status = $? >> 8;
|
||||
if ( $status || logDebugging() ) {
|
||||
|
@ -969,7 +972,7 @@ sub patchDB {
|
|||
my $dbh = shift;
|
||||
my $version = shift;
|
||||
|
||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
|
||||
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ) if $Config{ZM_DB_HOST};
|
||||
my $command = 'mysql';
|
||||
if ( defined($portOrSocket) ) {
|
||||
if ( $portOrSocket =~ /^\// ) {
|
||||
|
@ -977,12 +980,12 @@ sub patchDB {
|
|||
} else {
|
||||
$command .= ' -h'.$host.' -P'.$portOrSocket;
|
||||
}
|
||||
} else {
|
||||
} elsif ( $host ) {
|
||||
$command .= ' -h'.$host;
|
||||
}
|
||||
if ( $dbUser ) {
|
||||
$command .= ' -u'.$dbUser;
|
||||
$command .= ' -p"'.$dbPass.'"' if $dbPass;
|
||||
$command .= ' -p\''.$dbPass.'\'' if $dbPass;
|
||||
}
|
||||
$command .= ' '.$Config{ZM_DB_NAME}.' < ';
|
||||
if ( $updateDir ) {
|
||||
|
|
|
@ -48,11 +48,12 @@ Camera::Camera(
|
|||
record_audio(p_record_audio),
|
||||
bytes(0)
|
||||
{
|
||||
linesize = width * colours;
|
||||
pixels = width * height;
|
||||
imagesize = pixels * colours;
|
||||
imagesize = height * linesize;
|
||||
|
||||
Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",
|
||||
monitor_id, width, height, colours, subpixelorder, capture);
|
||||
Debug(2, "New camera id: %d width: %d line size: %d height: %d colours: %d subpixelorder: %d capture: %d",
|
||||
monitor_id, width, linesize, height, colours, subpixelorder, capture);
|
||||
|
||||
monitor = NULL;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ protected:
|
|||
Monitor * monitor; // Null on instantiation, set as soon as possible.
|
||||
SourceType type;
|
||||
unsigned int width;
|
||||
unsigned int linesize;
|
||||
unsigned int height;
|
||||
unsigned int colours;
|
||||
unsigned int subpixelorder;
|
||||
|
@ -69,6 +70,7 @@ public:
|
|||
bool IsLibvlc() const { return type == LIBVLC_SRC; }
|
||||
bool IscURL() const { return type == CURL_SRC; }
|
||||
unsigned int Width() const { return width; }
|
||||
unsigned int LineSize() const { return linesize; }
|
||||
unsigned int Height() const { return height; }
|
||||
unsigned int Colours() const { return colours; }
|
||||
unsigned int SubpixelOrder() const { return subpixelorder; }
|
||||
|
|
|
@ -206,7 +206,12 @@ Event::Event(
|
|||
/* X264 MP4 video writer */
|
||||
if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) {
|
||||
#if ZM_HAVE_VIDEOWRITER_X264MP4
|
||||
videowriter = new X264MP4Writer(video_file, monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder(), monitor->GetOptEncoderParams());
|
||||
videowriter = new X264MP4Writer(video_file,
|
||||
monitor->Width(),
|
||||
monitor->Height(),
|
||||
monitor->Colours(),
|
||||
monitor->SubpixelOrder(),
|
||||
monitor->GetOptEncoderParamsVec());
|
||||
#else
|
||||
Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)");
|
||||
#endif
|
||||
|
|
|
@ -807,29 +807,38 @@ Debug(1, "Loading image");
|
|||
|
||||
if ( send_raw ) {
|
||||
#if HAVE_SENDFILE
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size);
|
||||
if ( 0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size) ) {
|
||||
fclose(fdj); /* Close the file handle */
|
||||
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if ( zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size ) {
|
||||
/* sendfile() failed, use standard way instead */
|
||||
img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj );
|
||||
img_buffer_size = fread(img_buffer, 1, sizeof(temp_img_buffer), fdj);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
fclose(fdj); /* Close the file handle */
|
||||
Error("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size) )
|
||||
||
|
||||
( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 )
|
||||
) {
|
||||
fclose(fdj); /* Close the file handle */
|
||||
Error("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
Info("Unable to send raw frame %u: %s", curr_frame_id, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
fclose(fdj); /* Close the file handle */
|
||||
} else {
|
||||
Debug(3, "Content length: %d", img_buffer_size);
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size) )
|
||||
||
|
||||
( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) ) {
|
||||
Error("Unable to send stream frame: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ extern "C" {
|
|||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/avstring.h>
|
||||
#include "libavutil/audio_fifo.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
|
||||
/* LIBAVUTIL_VERSION_CHECK checks for the right version of libav and FFmpeg
|
||||
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
||||
|
|
|
@ -63,31 +63,31 @@ static enum AVPixelFormat get_hw_format(
|
|||
}
|
||||
#if !LIBAVUTIL_VERSION_CHECK(56, 22, 0, 14, 0)
|
||||
static enum AVPixelFormat find_fmt_by_hw_type(const enum AVHWDeviceType type) {
|
||||
enum AVPixelFormat fmt;
|
||||
switch (type) {
|
||||
enum AVPixelFormat fmt;
|
||||
switch (type) {
|
||||
case AV_HWDEVICE_TYPE_VAAPI:
|
||||
fmt = AV_PIX_FMT_VAAPI;
|
||||
break;
|
||||
fmt = AV_PIX_FMT_VAAPI;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_DXVA2:
|
||||
fmt = AV_PIX_FMT_DXVA2_VLD;
|
||||
break;
|
||||
fmt = AV_PIX_FMT_DXVA2_VLD;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_D3D11VA:
|
||||
fmt = AV_PIX_FMT_D3D11;
|
||||
break;
|
||||
fmt = AV_PIX_FMT_D3D11;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_VDPAU:
|
||||
fmt = AV_PIX_FMT_VDPAU;
|
||||
break;
|
||||
fmt = AV_PIX_FMT_VDPAU;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_CUDA:
|
||||
fmt = AV_PIX_FMT_CUDA;
|
||||
break;
|
||||
fmt = AV_PIX_FMT_CUDA;
|
||||
break;
|
||||
case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
|
||||
fmt = AV_PIX_FMT_VIDEOTOOLBOX;
|
||||
break;
|
||||
fmt = AV_PIX_FMT_VIDEOTOOLBOX;
|
||||
break;
|
||||
default:
|
||||
fmt = AV_PIX_FMT_NONE;
|
||||
break;
|
||||
}
|
||||
return fmt;
|
||||
fmt = AV_PIX_FMT_NONE;
|
||||
break;
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -174,6 +174,20 @@ FfmpegCamera::FfmpegCamera(
|
|||
} else {
|
||||
Panic("Unexpected colours: %d", colours);
|
||||
}
|
||||
|
||||
// sws_scale needs 32bit aligned width and an extra 16 bytes padding, so recalculate imagesize, which was width*height*bytes_per_pixel
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
alignment = 32;
|
||||
imagesize = av_image_get_buffer_size(imagePixFormat, width, height, alignment);
|
||||
// av_image_get_linesize isn't aligned, so we have to do that.
|
||||
linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), alignment);
|
||||
#else
|
||||
alignment = 1;
|
||||
linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), alignment);
|
||||
imagesize = avpicture_get_size(imagePixFormat, width, height);
|
||||
#endif
|
||||
|
||||
Debug(1, "ffmpegcamera: width %d height %d linesize %d colours %d imagesize %d", width, height, linesize, colours, imagesize);
|
||||
} // FfmpegCamera::FfmpegCamera
|
||||
|
||||
FfmpegCamera::~FfmpegCamera() {
|
||||
|
@ -194,12 +208,12 @@ void FfmpegCamera::Terminate() {
|
|||
|
||||
int FfmpegCamera::PrimeCapture() {
|
||||
if ( mCanCapture ) {
|
||||
Info("Priming capture from %s, Closing", mPath.c_str());
|
||||
Debug(1, "Priming capture from %s, Closing", mPath.c_str());
|
||||
Close();
|
||||
}
|
||||
mVideoStreamId = -1;
|
||||
mAudioStreamId = -1;
|
||||
Info("Priming capture from %s", mPath.c_str());
|
||||
Debug(1, "Priming capture from %s", mPath.c_str());
|
||||
|
||||
return OpenFfmpeg();
|
||||
}
|
||||
|
@ -608,16 +622,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
|||
mFrame->width = width;
|
||||
mFrame->height = height;
|
||||
|
||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||
int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
|
||||
#else
|
||||
int pSize = avpicture_get_size(imagePixFormat, width, height);
|
||||
#endif
|
||||
|
||||
if ( (unsigned int)pSize != imagesize ) {
|
||||
Error("Image size mismatch. Required: %d Available: %d", pSize, imagesize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if HAVE_LIBSWSCALE
|
||||
if ( !sws_isSupportedInput(mVideoCodecContext->pix_fmt) ) {
|
||||
|
@ -976,10 +980,12 @@ int FfmpegCamera::CaptureAndRecord(
|
|||
return -1;
|
||||
}
|
||||
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 89, 0, 89, 0)
|
||||
if ( (ret == AVERROR_INVALIDDATA ) && (hw_pix_fmt != AV_PIX_FMT_NONE) ) {
|
||||
use_hwaccel = false;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
zm_av_packet_unref(&packet);
|
||||
|
@ -1087,11 +1093,18 @@ int FfmpegCamera::transfer_to_image(
|
|||
int size = av_image_fill_arrays(
|
||||
output_frame->data, output_frame->linesize,
|
||||
directbuffer, imagePixFormat, width, height,
|
||||
(AV_PIX_FMT_RGBA == imagePixFormat ? 32 : 1)
|
||||
alignment
|
||||
);
|
||||
if ( size < 0 ) {
|
||||
Error("Problem setting up data pointers into image %s",
|
||||
av_make_error_string(size).c_str());
|
||||
} else {
|
||||
Debug(4, "av_image_fill_array %dx%d alignment: %d = %d, buffer size is %d",
|
||||
width, height, alignment, size, image.Size());
|
||||
}
|
||||
Debug(1, "ffmpegcamera: width %d height %d linesize %d colours %d imagesize %d", width, height, linesize, colours, imagesize);
|
||||
if ( linesize != (unsigned int)output_frame->linesize[0] ) {
|
||||
Error("Bad linesize expected %d got %d", linesize, output_frame->linesize[0]);
|
||||
}
|
||||
#else
|
||||
avpicture_fill((AVPicture *)output_frame, directbuffer,
|
||||
|
|
|
@ -45,6 +45,8 @@ class FfmpegCamera : public Camera {
|
|||
std::string hwaccel_device;
|
||||
|
||||
int frameCount;
|
||||
|
||||
int alignment; /* ffmpeg wants line sizes to be 32bit aligned. Especially 4.3+ */
|
||||
|
||||
#if HAVE_LIBAVFORMAT
|
||||
AVFormatContext *mFormatContext;
|
||||
|
|
|
@ -19,7 +19,7 @@ FFmpeg_Input::~FFmpeg_Input() {
|
|||
avcodec_close(streams[i].context);
|
||||
streams[i].context = NULL;
|
||||
}
|
||||
delete streams;
|
||||
delete[] streams;
|
||||
streams = NULL;
|
||||
}
|
||||
if ( frame ) {
|
||||
|
|
582
src/zm_image.cpp
582
src/zm_image.cpp
File diff suppressed because it is too large
Load Diff
|
@ -152,9 +152,11 @@ protected:
|
|||
static struct zm_error_mgr jpg_err;
|
||||
|
||||
unsigned int width;
|
||||
unsigned int linesize;
|
||||
unsigned int height;
|
||||
unsigned int pixels;
|
||||
unsigned int colours;
|
||||
unsigned int padding;
|
||||
unsigned int size;
|
||||
unsigned int subpixelorder;
|
||||
unsigned long allocation;
|
||||
|
@ -165,15 +167,18 @@ protected:
|
|||
|
||||
public:
|
||||
Image();
|
||||
explicit Image( const char *filename );
|
||||
Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0);
|
||||
explicit Image(const char *filename);
|
||||
Image(int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0, unsigned int padding=0);
|
||||
Image(int p_width, int p_linesize, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0, unsigned int padding=0);
|
||||
explicit Image( const Image &p_image );
|
||||
explicit Image( const AVFrame *frame );
|
||||
|
||||
~Image();
|
||||
static void Initialise();
|
||||
static void Deinitialise();
|
||||
|
||||
inline unsigned int Width() const { return width; }
|
||||
inline unsigned int LineSize() const { return linesize; }
|
||||
inline unsigned int Height() const { return height; }
|
||||
inline unsigned int Pixels() const { return pixels; }
|
||||
inline unsigned int Colours() const { return colours; }
|
||||
|
@ -182,7 +187,7 @@ public:
|
|||
|
||||
/* Internal buffer should not be modified from functions outside of this class */
|
||||
inline const uint8_t* Buffer() const { return buffer; }
|
||||
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return &buffer[colours*((y*width)+x)]; }
|
||||
inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return &buffer[(y*linesize)+x]; }
|
||||
/* Request writeable buffer */
|
||||
uint8_t* WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder);
|
||||
|
||||
|
@ -193,21 +198,34 @@ public:
|
|||
if ( !holdbuffer )
|
||||
DumpImgBuffer();
|
||||
|
||||
width = height = colours = size = pixels = subpixelorder = 0;
|
||||
width = linesize = height = colours = size = pixels = subpixelorder = 0;
|
||||
}
|
||||
|
||||
void Assign( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size);
|
||||
void Assign( const Image &image );
|
||||
void AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype);
|
||||
void Assign(
|
||||
unsigned int p_width,
|
||||
unsigned int p_height,
|
||||
unsigned int p_colours,
|
||||
unsigned int p_subpixelorder,
|
||||
const uint8_t* new_buffer,
|
||||
const size_t buffer_size);
|
||||
void Assign(const Image &image);
|
||||
void AssignDirect(
|
||||
const unsigned int p_width,
|
||||
const unsigned int p_height,
|
||||
const unsigned int p_colours,
|
||||
const unsigned int p_subpixelorder,
|
||||
uint8_t *new_buffer,
|
||||
const size_t buffer_size,
|
||||
const int p_buffertype);
|
||||
|
||||
inline void CopyBuffer( const Image &image ) {
|
||||
inline void CopyBuffer(const Image &image) {
|
||||
Assign(image);
|
||||
}
|
||||
inline Image &operator=( const Image &image ) {
|
||||
inline Image &operator=(const Image &image) {
|
||||
Assign(image);
|
||||
return *this;
|
||||
}
|
||||
inline Image &operator=( const unsigned char *new_buffer ) {
|
||||
inline Image &operator=(const unsigned char *new_buffer) {
|
||||
(*fptr_imgbufcpy)(buffer, new_buffer, size);
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -504,7 +504,7 @@ LocalCamera::LocalCamera(
|
|||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if ( config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 35 ) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
|
@ -616,7 +616,7 @@ LocalCamera::LocalCamera(
|
|||
}
|
||||
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8 ) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if ( config.cpu_extensions && sseversion >= 35 ) {
|
||||
if ( config.cpu_extensions && sse_version >= 35 ) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
|
|
|
@ -131,12 +131,12 @@ Monitor::MonitorLink::~MonitorLink() {
|
|||
}
|
||||
|
||||
bool Monitor::MonitorLink::connect() {
|
||||
if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) {
|
||||
if ( !last_connect_time || (time( 0 ) - last_connect_time) > ZM_MAX_RESTART_DELAY ) {
|
||||
last_connect_time = time( 0 );
|
||||
|
||||
mem_size = sizeof(SharedData) + sizeof(TriggerData);
|
||||
|
||||
Debug( 1, "link.mem.size=%d", mem_size );
|
||||
Debug(1, "link.mem.size=%d", mem_size);
|
||||
#if ZM_MEM_MAPPED
|
||||
map_fd = open( mem_file, O_RDWR, (mode_t)0600 );
|
||||
if ( map_fd < 0 ) {
|
||||
|
@ -379,6 +379,7 @@ Monitor::Monitor(
|
|||
|
||||
strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-1);
|
||||
strncpy(label_format, p_label_format, sizeof(label_format)-1);
|
||||
Debug(1, "encoder params %s", encoderparams.c_str());
|
||||
|
||||
// Change \n to actual line feeds
|
||||
char *token_ptr = label_format;
|
||||
|
@ -531,6 +532,7 @@ Monitor::Monitor(
|
|||
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;
|
||||
|
@ -605,7 +607,7 @@ bool Monitor::connect() {
|
|||
if ( mem_ptr == MAP_FAILED )
|
||||
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);
|
||||
}
|
||||
|
@ -1406,9 +1408,6 @@ bool Monitor::Analyse() {
|
|||
score += trigger_data->trigger_score;
|
||||
Debug(1, "Triggered on score += %d => %d", trigger_data->trigger_score, score);
|
||||
if ( !event ) {
|
||||
// How could it have a length already?
|
||||
//if ( cause.length() )
|
||||
//cause += ", ";
|
||||
cause += trigger_data->trigger_cause;
|
||||
}
|
||||
Event::StringSet noteSet;
|
||||
|
@ -1488,6 +1487,7 @@ bool Monitor::Analyse() {
|
|||
score += 50;
|
||||
}
|
||||
} else {
|
||||
Debug(1, "Linked monitor %d %d is not connected. Connecting.", i, linked_monitors[i]->Id());
|
||||
linked_monitors[i]->connect();
|
||||
}
|
||||
} // end foreach linked_monit
|
||||
|
@ -1502,7 +1502,7 @@ bool Monitor::Analyse() {
|
|||
|
||||
if ( section_length
|
||||
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= section_length )
|
||||
&& ( (event_close_mode != CLOSE_TIME) || ! ( timestamp->tv_sec % section_length ) )
|
||||
&& ( (function == MOCORD && (event_close_mode != CLOSE_TIME)) || ! ( timestamp->tv_sec % section_length ) )
|
||||
) {
|
||||
Info("%s: %03d - Closing event %" PRIu64 ", section end forced %d - %d = %d >= %d",
|
||||
name, image_count, event->Id(),
|
||||
|
@ -1515,7 +1515,6 @@ bool Monitor::Analyse() {
|
|||
} // end if event
|
||||
|
||||
if ( !event ) {
|
||||
|
||||
// Create event
|
||||
event = new Event(this, *timestamp, "Continuous", noteSetMap, videoRecording);
|
||||
shared_data->last_event = event->Id();
|
||||
|
@ -1529,7 +1528,6 @@ bool Monitor::Analyse() {
|
|||
if ( state == IDLE ) {
|
||||
shared_data->state = state = TAPE;
|
||||
}
|
||||
|
||||
} // end if ! event
|
||||
} // end if function == RECORD || function == MOCORD)
|
||||
} // end if !signal_change && signal
|
||||
|
@ -1542,7 +1540,7 @@ bool Monitor::Analyse() {
|
|||
&& (event_close_mode == CLOSE_ALARM)
|
||||
&& ( ( timestamp->tv_sec - video_store_data->recording.tv_sec ) >= min_section_length )
|
||||
) {
|
||||
Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins",
|
||||
Info("%s: %03d - Closing event %" PRIu64 ", continuous end, alarm begins",
|
||||
name, image_count, event->Id());
|
||||
closeEvent();
|
||||
} else if ( event ) {
|
||||
|
@ -1553,7 +1551,6 @@ bool Monitor::Analyse() {
|
|||
);
|
||||
}
|
||||
if ( (!pre_event_count) || (Event::PreAlarmCount() >= alarm_frame_count-1) ) {
|
||||
shared_data->state = state = ALARM;
|
||||
// lets construct alarm cause. It will contain cause + names of zones alarmed
|
||||
std::string alarm_cause = "";
|
||||
for ( int i=0; i < n_zones; i++ ) {
|
||||
|
@ -1638,6 +1635,7 @@ bool Monitor::Analyse() {
|
|||
event->SavePreAlarmFrames();
|
||||
}
|
||||
}
|
||||
shared_data->state = state = ALARM;
|
||||
} else if ( state != PREALARM ) {
|
||||
Info("%s: %03d - Gone into prealarm state", name, image_count);
|
||||
shared_data->state = state = PREALARM;
|
||||
|
@ -1697,17 +1695,10 @@ bool Monitor::Analyse() {
|
|||
} // end if zone is alarmed
|
||||
} // end foreach zone
|
||||
|
||||
if ( got_anal_image ) {
|
||||
if ( state == PREALARM )
|
||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score, &alarm_image);
|
||||
else
|
||||
event->AddFrame(snap_image, *timestamp, score, &alarm_image);
|
||||
} else {
|
||||
if ( state == PREALARM )
|
||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score);
|
||||
else
|
||||
event->AddFrame(snap_image, *timestamp, score);
|
||||
}
|
||||
if ( state == PREALARM )
|
||||
Event::AddPreAlarmFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
|
||||
else
|
||||
event->AddFrame(snap_image, *timestamp, score, (got_anal_image?&alarm_image:NULL));
|
||||
} else {
|
||||
// Not doing alarm frame storage
|
||||
if ( state == PREALARM ) {
|
||||
|
@ -1743,7 +1734,6 @@ bool Monitor::Analyse() {
|
|||
//set up video store data
|
||||
snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile());
|
||||
video_store_data->recording = event->StartTime();
|
||||
|
||||
}
|
||||
} // end if event
|
||||
|
||||
|
@ -2498,7 +2488,7 @@ int Monitor::Capture() {
|
|||
|
||||
if ( capture_image->Size() > camera->ImageSize() ) {
|
||||
Error("Captured image %d does not match expected size %d check width, height and colour depth",
|
||||
capture_image->Size(),camera->ImageSize() );
|
||||
capture_image->Size(), camera->ImageSize() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ protected:
|
|||
}
|
||||
|
||||
inline bool isConnected() const {
|
||||
return( connected );
|
||||
return connected && shared_data->valid;
|
||||
}
|
||||
inline time_t getLastConnectTime() const {
|
||||
return( last_connect_time );
|
||||
|
@ -463,7 +463,8 @@ public:
|
|||
|
||||
int GetOptSaveJPEGs() const { return savejpegs; }
|
||||
VideoWriter GetOptVideoWriter() const { return videowriter; }
|
||||
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return &encoderparamsvec; }
|
||||
const std::vector<EncoderParameter_t>* GetOptEncoderParamsVec() const { return &encoderparamsvec; }
|
||||
const std::string GetOptEncoderParams() const { return encoderparams; }
|
||||
uint64_t GetVideoWriterEventId() const { return video_store_data->current_event; }
|
||||
void SetVideoWriterEventId( unsigned long long p_event_id ) { video_store_data->current_event = p_event_id; }
|
||||
struct timeval GetVideoWriterStartTime() const { return video_store_data->recording; }
|
||||
|
|
|
@ -329,8 +329,11 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) {
|
|||
gettimeofday(&frameStartTime, NULL);
|
||||
|
||||
fputs("--ZoneMinderFrame\r\nContent-Type: image/jpeg\r\n", stdout);
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size))
|
||||
||
|
||||
(fwrite(img_buffer, img_buffer_size, 1, stdout) != 1)
|
||||
) {
|
||||
if ( !zm_terminate )
|
||||
Warning("Unable to send stream frame: %s", strerror(errno));
|
||||
return false;
|
||||
|
@ -385,7 +388,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
|||
gettimeofday(&frameStartTime, NULL);
|
||||
|
||||
fputs("--ZoneMinderFrame\r\n", stdout);
|
||||
switch( type ) {
|
||||
switch ( type ) {
|
||||
case STREAM_JPEG :
|
||||
send_image->EncodeJpeg(img_buffer, &img_buffer_size);
|
||||
fputs("Content-Type: image/jpeg\r\n", stdout);
|
||||
|
@ -410,8 +413,11 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) {
|
|||
Error("Unexpected frame type %d", type);
|
||||
return false;
|
||||
}
|
||||
fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size);
|
||||
if ( fwrite(img_buffer, img_buffer_size, 1, stdout) != 1 ) {
|
||||
if (
|
||||
(0 > fprintf(stdout, "Content-Length: %d\r\n\r\n", img_buffer_size))
|
||||
||
|
||||
(fwrite(img_buffer, img_buffer_size, 1, stdout) != 1)
|
||||
) {
|
||||
if ( !zm_terminate ) {
|
||||
// If the pipe was closed, we will get signalled SIGPIPE to exit, which will set zm_terminate
|
||||
Warning("Unable to send stream frame: %s", strerror(errno));
|
||||
|
|
|
@ -618,8 +618,8 @@ int RemoteCameraHttp::GetResponse() {
|
|||
static char *content_type_header;
|
||||
static char *boundary_header;
|
||||
static char *authenticate_header;
|
||||
static char subcontent_length_header[32];
|
||||
static char subcontent_type_header[64];
|
||||
static char subcontent_length_header[33];
|
||||
static char subcontent_type_header[65];
|
||||
|
||||
static char http_version[16];
|
||||
static char status_code[16];
|
||||
|
@ -892,25 +892,37 @@ int RemoteCameraHttp::GetResponse() {
|
|||
}
|
||||
}
|
||||
|
||||
Debug( 6, "%d: %s", subheader_len, subheader_ptr );
|
||||
Debug(6, "%d: %s", subheader_len, subheader_ptr);
|
||||
|
||||
if ( (crlf = mempbrk( subheader_ptr, "\r\n", subheader_len )) ) {
|
||||
if ( (crlf = mempbrk(subheader_ptr, "\r\n", subheader_len)) ) {
|
||||
//subheaders[n_subheaders++] = subheader_ptr;
|
||||
n_subheaders++;
|
||||
|
||||
if ( !boundary_header && (strncasecmp( subheader_ptr, content_boundary, content_boundary_len ) == 0) ) {
|
||||
if ( !boundary_header && (strncasecmp(subheader_ptr, content_boundary, content_boundary_len) == 0) ) {
|
||||
boundary_header = subheader_ptr;
|
||||
Debug( 4, "Got boundary subheader '%s'", subheader_ptr );
|
||||
} else if ( !subcontent_length_header[0] && (strncasecmp( subheader_ptr, content_length_match, content_length_match_len) == 0) ) {
|
||||
strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) );
|
||||
*(subcontent_length_header+strcspn( subcontent_length_header, "\r\n" )) = '\0';
|
||||
Debug( 4, "Got content length subheader '%s'", subcontent_length_header );
|
||||
Debug(4, "Got boundary subheader '%s'", subheader_ptr);
|
||||
} else if (
|
||||
!subcontent_length_header[0]
|
||||
&&
|
||||
(strncasecmp(subheader_ptr, content_length_match, content_length_match_len) == 0)
|
||||
) {
|
||||
strncpy(
|
||||
subcontent_length_header,
|
||||
subheader_ptr+content_length_match_len,
|
||||
sizeof(subcontent_length_header)-1
|
||||
);
|
||||
*(subcontent_length_header+strcspn(subcontent_length_header, "\r\n")) = '\0';
|
||||
Debug(4, "Got content length subheader '%s'", subcontent_length_header);
|
||||
} else if ( !subcontent_type_header[0] && (strncasecmp( subheader_ptr, content_type_match, content_type_match_len) == 0) ) {
|
||||
strncpy( subcontent_type_header, subheader_ptr+content_type_match_len, sizeof(subcontent_type_header) );
|
||||
*(subcontent_type_header+strcspn( subcontent_type_header, "\r\n" )) = '\0';
|
||||
Debug( 4, "Got content type subheader '%s'", subcontent_type_header );
|
||||
strncpy(
|
||||
subcontent_type_header,
|
||||
subheader_ptr+content_type_match_len,
|
||||
sizeof(subcontent_type_header)-1
|
||||
);
|
||||
*(subcontent_type_header+strcspn(subcontent_type_header, "\r\n")) = '\0';
|
||||
Debug(4, "Got content type subheader '%s'", subcontent_type_header);
|
||||
} else {
|
||||
Debug( 6, "Got ignored subheader '%s' found", subheader_ptr );
|
||||
Debug(6, "Got ignored subheader '%s' found", subheader_ptr);
|
||||
}
|
||||
subheader_ptr = crlf;
|
||||
subheader_len -= buffer.consume( subheader_ptr-(char *)buffer );
|
||||
|
|
123
src/zm_utils.cpp
123
src/zm_utils.cpp
|
@ -35,7 +35,7 @@
|
|||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
unsigned int sseversion = 0;
|
||||
unsigned int sse_version = 0;
|
||||
unsigned int neonversion = 0;
|
||||
|
||||
std::string trimSet(std::string str, std::string trimset) {
|
||||
|
@ -44,12 +44,9 @@ std::string trimSet(std::string str, std::string trimset) {
|
|||
size_t endpos = str.find_last_not_of(trimset); // Find the first character position from reverse af
|
||||
|
||||
// if all spaces or empty return an empty string
|
||||
if(( std::string::npos == startpos ) || ( std::string::npos == endpos))
|
||||
{
|
||||
if ( ( std::string::npos == startpos ) || ( std::string::npos == endpos ) )
|
||||
return std::string("");
|
||||
}
|
||||
else
|
||||
return str.substr( startpos, endpos-startpos+1 );
|
||||
return str.substr(startpos, endpos-startpos+1);
|
||||
}
|
||||
|
||||
std::string trimSpaces(const std::string &str) {
|
||||
|
@ -57,48 +54,46 @@ std::string trimSpaces(const std::string &str) {
|
|||
}
|
||||
|
||||
std::string replaceAll(std::string str, std::string from, std::string to) {
|
||||
if(from.empty())
|
||||
if ( from.empty() )
|
||||
return str;
|
||||
size_t start_pos = 0;
|
||||
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||
while ( (start_pos = str.find(from, start_pos)) != std::string::npos ) {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
const std::string stringtf( const char *format, ... )
|
||||
{
|
||||
const std::string stringtf( const char *format, ... ) {
|
||||
va_list ap;
|
||||
char tempBuffer[8192];
|
||||
std::string tempString;
|
||||
|
||||
va_start(ap, format );
|
||||
vsnprintf( tempBuffer, sizeof(tempBuffer), format , ap );
|
||||
va_start(ap, format);
|
||||
vsnprintf(tempBuffer, sizeof(tempBuffer), format , ap);
|
||||
va_end(ap);
|
||||
|
||||
tempString = tempBuffer;
|
||||
|
||||
return( tempString );
|
||||
return tempString;
|
||||
}
|
||||
|
||||
const std::string stringtf( const std::string format, ... )
|
||||
{
|
||||
const std::string stringtf(const std::string format, ...) {
|
||||
va_list ap;
|
||||
char tempBuffer[8192];
|
||||
std::string tempString;
|
||||
|
||||
va_start(ap, format );
|
||||
vsnprintf( tempBuffer, sizeof(tempBuffer), format.c_str() , ap );
|
||||
va_start(ap, format);
|
||||
vsnprintf(tempBuffer, sizeof(tempBuffer), format.c_str(), ap);
|
||||
va_end(ap);
|
||||
|
||||
tempString = tempBuffer;
|
||||
|
||||
return( tempString );
|
||||
return tempString;
|
||||
}
|
||||
|
||||
bool startsWith(const std::string &haystack, const std::string &needle) {
|
||||
return( haystack.substr(0, needle.length()) == needle );
|
||||
return ( haystack.substr(0, needle.length()) == needle );
|
||||
}
|
||||
|
||||
StringVector split(const std::string &string, const std::string &chars, int limit) {
|
||||
|
@ -145,8 +140,7 @@ const std::string join(const StringVector &v, const char * delim=",") {
|
|||
const std::string base64Encode(const std::string &inString) {
|
||||
static char base64_table[64] = { '\0' };
|
||||
|
||||
if ( !base64_table[0] )
|
||||
{
|
||||
if ( !base64_table[0] ) {
|
||||
int i = 0;
|
||||
for ( char c = 'A'; c <= 'Z'; c++ )
|
||||
base64_table[i++] = c;
|
||||
|
@ -159,59 +153,52 @@ const std::string base64Encode(const std::string &inString) {
|
|||
}
|
||||
|
||||
std::string outString;
|
||||
outString.reserve( 2 * inString.size() );
|
||||
outString.reserve(2 * inString.size());
|
||||
|
||||
const char *inPtr = inString.c_str();
|
||||
while( *inPtr )
|
||||
{
|
||||
while ( *inPtr ) {
|
||||
unsigned char selection = *inPtr >> 2;
|
||||
unsigned char remainder = (*inPtr++ & 0x03) << 4;
|
||||
outString += base64_table[selection];
|
||||
|
||||
if ( *inPtr )
|
||||
{
|
||||
if ( *inPtr ) {
|
||||
selection = remainder | (*inPtr >> 4);
|
||||
remainder = (*inPtr++ & 0x0f) << 2;
|
||||
outString += base64_table[selection];
|
||||
|
||||
if ( *inPtr )
|
||||
{
|
||||
if ( *inPtr ) {
|
||||
selection = remainder | (*inPtr >> 6);
|
||||
outString += base64_table[selection];
|
||||
selection = (*inPtr++ & 0x3f);
|
||||
outString += base64_table[selection];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
outString += base64_table[remainder];
|
||||
outString += '=';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
outString += base64_table[remainder];
|
||||
outString += '=';
|
||||
outString += '=';
|
||||
}
|
||||
}
|
||||
return( outString );
|
||||
return outString;
|
||||
}
|
||||
|
||||
int split(const char* string, const char delim, std::vector<std::string>& items) {
|
||||
if(string == NULL)
|
||||
if ( string == NULL )
|
||||
return -1;
|
||||
|
||||
if(string[0] == 0)
|
||||
if ( string[0] == 0 )
|
||||
return -2;
|
||||
|
||||
std::string str(string);
|
||||
|
||||
while(true) {
|
||||
while ( true ) {
|
||||
size_t pos = str.find(delim);
|
||||
items.push_back(str.substr(0, pos));
|
||||
str.erase(0, pos+1);
|
||||
|
||||
if(pos == std::string::npos)
|
||||
if ( pos == std::string::npos )
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -219,16 +206,16 @@ int split(const char* string, const char delim, std::vector<std::string>& items)
|
|||
}
|
||||
|
||||
int pairsplit(const char* string, const char delim, std::string& name, std::string& value) {
|
||||
if(string == NULL)
|
||||
if ( string == NULL )
|
||||
return -1;
|
||||
|
||||
if(string[0] == 0)
|
||||
if ( string[0] == 0 )
|
||||
return -2;
|
||||
|
||||
std::string str(string);
|
||||
size_t pos = str.find(delim);
|
||||
|
||||
if(pos == std::string::npos || pos == 0 || pos >= str.length())
|
||||
if ( pos == std::string::npos || pos == 0 || pos >= str.length() )
|
||||
return -3;
|
||||
|
||||
name = str.substr(0, pos);
|
||||
|
@ -240,7 +227,7 @@ int pairsplit(const char* string, const char delim, std::string& name, std::stri
|
|||
/* Detect special hardware features, such as SIMD instruction sets */
|
||||
void hwcaps_detect() {
|
||||
neonversion = 0;
|
||||
sseversion = 0;
|
||||
sse_version = 0;
|
||||
#if (defined(__i386__) || defined(__x86_64__))
|
||||
/* x86 or x86-64 processor */
|
||||
uint32_t r_edx, r_ecx, r_ebx;
|
||||
|
@ -277,33 +264,33 @@ void hwcaps_detect() {
|
|||
);
|
||||
#endif
|
||||
|
||||
if (r_ebx & 0x00000020) {
|
||||
sseversion = 52; /* AVX2 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with AVX2");
|
||||
} else if (r_ecx & 0x10000000) {
|
||||
sseversion = 51; /* AVX */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with AVX");
|
||||
} else if (r_ecx & 0x00100000) {
|
||||
sseversion = 42; /* SSE4.2 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE4.2");
|
||||
} else if (r_ecx & 0x00080000) {
|
||||
sseversion = 41; /* SSE4.1 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE4.1");
|
||||
} else if (r_ecx & 0x00000200) {
|
||||
sseversion = 35; /* SSSE3 */
|
||||
if ( r_ebx & 0x00000020 ) {
|
||||
sse_version = 52; /* AVX2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with AVX2");
|
||||
} else if ( r_ecx & 0x10000000 ) {
|
||||
sse_version = 51; /* AVX */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with AVX");
|
||||
} else if ( r_ecx & 0x00100000 ) {
|
||||
sse_version = 42; /* SSE4.2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE4.2");
|
||||
} else if ( r_ecx & 0x00080000 ) {
|
||||
sse_version = 41; /* SSE4.1 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE4.1");
|
||||
} else if ( r_ecx & 0x00000200 ) {
|
||||
sse_version = 35; /* SSSE3 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSSE3");
|
||||
} else if (r_ecx & 0x00000001) {
|
||||
sseversion = 30; /* SSE3 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE3");
|
||||
} else if (r_edx & 0x04000000) {
|
||||
sseversion = 20; /* SSE2 */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE2");
|
||||
} else if (r_edx & 0x02000000) {
|
||||
sseversion = 10; /* SSE */
|
||||
Debug(1,"Detected a x86\\x86-64 processor with SSE");
|
||||
} else if ( r_ecx & 0x00000001 ) {
|
||||
sse_version = 30; /* SSE3 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE3");
|
||||
} else if ( r_edx & 0x04000000 ) {
|
||||
sse_version = 20; /* SSE2 */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE2");
|
||||
} else if ( r_edx & 0x02000000 ) {
|
||||
sse_version = 10; /* SSE */
|
||||
Debug(1, "Detected a x86\\x86-64 processor with SSE");
|
||||
} else {
|
||||
sseversion = 0;
|
||||
Debug(1,"Detected a x86\\x86-64 processor");
|
||||
sse_version = 0;
|
||||
Debug(1, "Detected a x86\\x86-64 processor");
|
||||
}
|
||||
#elif defined(__arm__)
|
||||
// ARM processor in 32bit mode
|
||||
|
|
|
@ -59,7 +59,7 @@ void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes);
|
|||
void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff);
|
||||
|
||||
void hwcaps_detect();
|
||||
extern unsigned int sseversion;
|
||||
extern unsigned int sse_version;
|
||||
extern unsigned int neonversion;
|
||||
|
||||
char *timeval_to_string( struct timeval tv );
|
||||
|
|
|
@ -37,11 +37,12 @@ VideoStore::VideoStore(
|
|||
const char *format_in,
|
||||
AVStream *p_video_in_stream,
|
||||
AVStream *p_audio_in_stream,
|
||||
Monitor *monitor
|
||||
Monitor *p_monitor
|
||||
) {
|
||||
|
||||
video_in_stream = p_video_in_stream;
|
||||
audio_in_stream = p_audio_in_stream;
|
||||
monitor = p_monitor;
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
//video_in_ctx = avcodec_alloc_context3(NULL);
|
||||
|
@ -213,11 +214,18 @@ VideoStore::VideoStore(
|
|||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
|
||||
#if 0
|
||||
# This is commented out because we are only doing passthrough right now
|
||||
/* I'm not entirely sure that this is a good idea. We may have to do it someday but really only when transcoding
|
||||
* * think what I was trying to achieve here was to have zm_dump_codecpar output nice info
|
||||
* */
|
||||
#if 0
|
||||
|
||||
AVDictionary *opts = 0;
|
||||
ret = av_dict_parse_string(&opts, monitor->GetOptEncoderParams().c_str(), "=", ",", 0);
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not parse ffmpeg encoder options '%s'", monitor->GetOptEncoderParams().c_str());
|
||||
}
|
||||
|
||||
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
|
||||
Warning("Can't open video codec (%s) %s",
|
||||
video_out_codec->name,
|
||||
|
@ -404,21 +412,39 @@ bool VideoStore::open() {
|
|||
}
|
||||
|
||||
zm_dump_stream_format(oc, 0, 0, 1);
|
||||
if (audio_out_stream) zm_dump_stream_format(oc, 1, 0, 1);
|
||||
if ( audio_out_stream ) zm_dump_stream_format(oc, 1, 0, 1);
|
||||
|
||||
AVDictionary *opts = NULL;
|
||||
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||
// Shiboleth reports that this may break seeking in mp4 before it downloads
|
||||
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
|
||||
// av_dict_set(&opts, "movflags",
|
||||
// "frag_keyframe+empty_moov+default_base_moof", 0);
|
||||
|
||||
std::string option_string = monitor->GetOptEncoderParams();
|
||||
ret = av_dict_parse_string(&opts, option_string.c_str(), "=", ",\n", 0);
|
||||
if ( ret < 0 ) {
|
||||
Warning("Could not parse ffmpeg output options '%s'", option_string.c_str());
|
||||
}
|
||||
|
||||
const AVDictionaryEntry *movflags_entry = av_dict_get(opts, "movflags", NULL, AV_DICT_MATCH_CASE);
|
||||
if ( !movflags_entry ) {
|
||||
Debug(1, "setting movflags to frag_keyframe+empty_moov");
|
||||
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
|
||||
// Shiboleth reports that this may break seeking in mp4 before it downloads
|
||||
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
|
||||
// av_dict_set(&opts, "movflags",
|
||||
// "frag_keyframe+empty_moov+default_base_moof", 0);
|
||||
} else {
|
||||
Debug(1, "using movflags %s", movflags_entry->value);
|
||||
}
|
||||
if ( (ret = avformat_write_header(oc, &opts)) < 0 ) {
|
||||
// if ((ret = avformat_write_header(oc, &opts)) < 0) {
|
||||
Warning("Unable to set movflags to frag_custom+dash+delay_moov");
|
||||
/* Write the stream header, if any. */
|
||||
Warning("Unable to set movflags trying with defaults.");
|
||||
ret = avformat_write_header(oc, NULL);
|
||||
} else if (av_dict_count(opts) != 0) {
|
||||
Warning("some options not set");
|
||||
} else if ( av_dict_count(opts) != 0 ) {
|
||||
Info("some options not used, turn on debugging for a list.");
|
||||
AVDictionaryEntry *e = NULL;
|
||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||
Debug(1, "Encoder Option %s=>%s", e->key, e->value);
|
||||
if ( !e->value ) {
|
||||
av_dict_set(&opts, e->key, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( opts ) av_dict_free(&opts);
|
||||
if ( ret < 0 ) {
|
||||
|
|
|
@ -19,7 +19,6 @@ extern "C" {
|
|||
|
||||
class VideoStore {
|
||||
private:
|
||||
|
||||
AVOutputFormat *out_format;
|
||||
AVFormatContext *oc;
|
||||
|
||||
|
@ -30,6 +29,7 @@ private:
|
|||
AVStream *video_in_stream;
|
||||
|
||||
AVStream *audio_in_stream;
|
||||
Monitor *monitor;
|
||||
|
||||
// Move this into the object so that we aren't constantly allocating/deallocating it on the stack
|
||||
AVPacket opkt;
|
||||
|
|
|
@ -227,7 +227,7 @@ bool Zone::CheckAlarms(const Image *delta_image) {
|
|||
|
||||
Debug(4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y);
|
||||
|
||||
/* if(config.cpu_extensions && sseversion >= 20) {
|
||||
/* if(config.cpu_extensions && sse_version >= 20) {
|
||||
sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
} else {
|
||||
std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count);
|
||||
|
|
|
@ -259,7 +259,8 @@ int main(int argc, char *argv[]) {
|
|||
Debug(1, "Failed to prime capture of initial monitor");
|
||||
}
|
||||
prime_capture_log_count ++;
|
||||
sleep(10);
|
||||
if ( !zm_terminate )
|
||||
sleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ fi;
|
|||
|
||||
if [ "$DISTROS" == "" ]; then
|
||||
if [ "$RELEASE" != "" ]; then
|
||||
DISTROS="xenial,bionic,disco,eoan,focal,trusty"
|
||||
DISTROS="xenial,bionic,focal,trusty"
|
||||
else
|
||||
DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
|
||||
fi;
|
||||
|
@ -220,14 +220,19 @@ IFS=',' ;for DISTRO in `echo "$DISTROS"`; do
|
|||
fi;
|
||||
|
||||
# Generate Changlog
|
||||
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]; then
|
||||
if [ "$DISTRO" == "trusty" ] || [ "$DISTRO" == "precise" ]
|
||||
then
|
||||
cp -Rpd distros/ubuntu1204 debian
|
||||
else
|
||||
if [ "$DISTRO" == "wheezy" ]; then
|
||||
cp -Rpd distros/debian debian
|
||||
else
|
||||
cp -Rpd distros/ubuntu1604 debian
|
||||
fi;
|
||||
|
||||
elif [ "$DISTRO" == "wheezy" ]
|
||||
then
|
||||
cp -Rpd distros/debian debian
|
||||
|
||||
elif [ "$DISTRO" == "beowulf" ]
|
||||
then
|
||||
cp -Rpd distros/beowulf debian
|
||||
else
|
||||
cp -Rpd distros/ubuntu1604 debian
|
||||
fi;
|
||||
|
||||
if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then
|
||||
|
|
|
@ -37,7 +37,7 @@ echo "Target subfolder set to $targetfolder"
|
|||
echo
|
||||
|
||||
echo "Running \$(rsync -v -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1)"
|
||||
rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -vvv' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
|
||||
rsync -v --ignore-missing-args --exclude 'external-repo.noarch.rpm' -e 'ssh -v' build/*.{rpm,deb,dsc,tar.xz,buildinfo,changes} zmrepo@zmrepo.zoneminder.com:${targetfolder}/ 2>&1
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo
|
||||
echo "Files copied successfully."
|
||||
|
|
|
@ -19,7 +19,7 @@ $statusData = array(
|
|||
'limit' => 1,
|
||||
'elements' => array(
|
||||
'MonitorCount' => array( 'sql' => 'count(*)' ),
|
||||
'ActiveMonitorCount' => array( 'sql' => 'count(if(Function != \'None\',1,NULL))' ),
|
||||
'ActiveMonitorCount' => array( 'sql' => 'count(if(`Function` != \'None\',1,NULL))' ),
|
||||
'State' => array( 'func' => 'daemonCheck()?'.translate('Running').':'.translate('Stopped') ),
|
||||
'Load' => array( 'func' => 'getLoad()' ),
|
||||
'Disk' => array( 'func' => 'getDiskPercent()' ),
|
||||
|
@ -211,17 +211,17 @@ function collectData() {
|
|||
$values = array();
|
||||
|
||||
$elements = &$entitySpec['elements'];
|
||||
$lc_elements = array_change_key_case( $elements );
|
||||
$lc_elements = array_change_key_case($elements);
|
||||
|
||||
$id = false;
|
||||
if ( isset($_REQUEST['id']) )
|
||||
if ( !is_array($_REQUEST['id']) )
|
||||
$id = array( validJsStr($_REQUEST['id']) );
|
||||
else
|
||||
$id = array_values( $_REQUEST['id'] );
|
||||
$id = array_values($_REQUEST['id']);
|
||||
|
||||
if ( !isset($_REQUEST['element']) )
|
||||
$_REQUEST['element'] = array_keys( $elements );
|
||||
$_REQUEST['element'] = array_keys($elements);
|
||||
else if ( !is_array($_REQUEST['element']) )
|
||||
$_REQUEST['element'] = array( validJsStr($_REQUEST['element']) );
|
||||
|
||||
|
@ -235,18 +235,18 @@ function collectData() {
|
|||
|
||||
foreach ( $_REQUEST['element'] as $element ) {
|
||||
if ( !($elementData = $lc_elements[strtolower($element)]) )
|
||||
ajaxError( 'Bad '.validJsStr($_REQUEST['entity']).' element '.$element );
|
||||
ajaxError('Bad '.validJsStr($_REQUEST['entity']).' element '.$element);
|
||||
if ( isset($elementData['func']) )
|
||||
$data[$element] = eval( 'return( '.$elementData['func'].' );' );
|
||||
$data[$element] = eval('return( '.$elementData['func'].' );');
|
||||
else if ( isset($elementData['postFunc']) )
|
||||
$postFuncs[$element] = $elementData['postFunc'];
|
||||
else if ( isset($elementData['zmu']) )
|
||||
$data[$element] = exec( escapeshellcmd( getZmuCommand( ' '.$elementData['zmu'] ) ) );
|
||||
$data[$element] = exec(escapeshellcmd(getZmuCommand(' '.$elementData['zmu'])));
|
||||
else {
|
||||
if ( isset($elementData['sql']) )
|
||||
$fieldSql[] = $elementData['sql'].' as '.$element;
|
||||
else
|
||||
$fieldSql[] = $element;
|
||||
$fieldSql[] = '`'.$element.'`';
|
||||
if ( isset($elementData['table']) && isset($elementData['join']) ) {
|
||||
$joinSql[] = 'left join '.$elementData['table'].' on '.$elementData['join'];
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ function collectData() {
|
|||
|
||||
preg_match('/^(\w+)\s*(ASC|DESC)?( NULLS FIRST)?$/i', $sort_field, $matches);
|
||||
if ( count($matches) ) {
|
||||
if ( in_array($matches[1], $fieldSql) ) {
|
||||
if ( in_array($matches[1], $fieldSql) or in_array('`'.$matches[1].'`', $fieldSql) ) {
|
||||
$sql .= $matches[1];
|
||||
} else {
|
||||
ZM\Error('Sort field ' . $matches[1] . ' not in SQL Fields');
|
||||
|
@ -296,7 +296,7 @@ function collectData() {
|
|||
$sql .= ' '.strtoupper($matches[3]);
|
||||
}
|
||||
} else {
|
||||
ZM\Error("Sort field didn't match regexp $sort_field");
|
||||
ZM\Error('Sort field didn\'t match regexp '.$sort_field);
|
||||
}
|
||||
} # end foreach sort field
|
||||
} # end if has sort
|
||||
|
@ -310,7 +310,7 @@ function collectData() {
|
|||
if ( !empty( $limit ) )
|
||||
$sql .= ' limit '.$limit_offset.$limit;
|
||||
if ( isset($limit) && $limit == 1 ) {
|
||||
if ( $sqlData = dbFetchOne( $sql, NULL, $values ) ) {
|
||||
if ( $sqlData = dbFetchOne($sql, NULL, $values) ) {
|
||||
foreach ( $postFuncs as $element=>$func )
|
||||
$sqlData[$element] = eval( 'return( '.$func.'( $sqlData ) );' );
|
||||
$data = array_merge( $data, $sqlData );
|
||||
|
|
|
@ -102,21 +102,21 @@ CakeLog::config('debug', array(
|
|||
'engine' => 'File',
|
||||
'types' => array('notice', 'info', 'debug'),
|
||||
'file' => 'cake_debug',
|
||||
'path' => '@ZM_LOGDIR@/'
|
||||
'path' => '@ZM_LOGDIR@/'
|
||||
));
|
||||
CakeLog::config('error', array(
|
||||
'engine' => 'File',
|
||||
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
|
||||
'file' => 'cake_error',
|
||||
'path' => '@ZM_LOGDIR@/'
|
||||
'path' => '@ZM_LOGDIR@/'
|
||||
));
|
||||
CakeLog::config('custom_path', array(
|
||||
'engine' => 'File',
|
||||
'path' => '@ZM_LOGDIR@/'
|
||||
'engine' => 'File',
|
||||
'path' => '@ZM_LOGDIR@/'
|
||||
));
|
||||
|
||||
Configure::write('ZM_CONFIG', '@ZM_CONFIG@');
|
||||
Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@');
|
||||
Configure::write('ZM_CONFIG', '@ZM_CONFIG@');
|
||||
Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@');
|
||||
Configure::write('ZM_VERSION', '@VERSION@');
|
||||
Configure::write('ZM_API_VERSION', '@API_VERSION@');
|
||||
|
||||
|
@ -128,27 +128,3 @@ global $configvals;
|
|||
foreach( $configvals as $key => $value) {
|
||||
Configure::write($key, $value);
|
||||
}
|
||||
if ( 0 ) {
|
||||
// No longer needed, but I want to keep the code for reference
|
||||
//
|
||||
// For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID
|
||||
if ( ! defined('ZM_SERVER_ID') ) {
|
||||
App::uses('ClassRegistry', 'Utility');
|
||||
$ServerModel = ClassRegistry::init('Server');
|
||||
if ( defined('ZM_SERVER_NAME') and ZM_SERVER_NAME ) {
|
||||
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_NAME) ) );
|
||||
if ( ! $Server ) {
|
||||
Error('Invalid Multi-Server configration detected. ZM_SERVER_NAME set to ' . ZM_SERVER_NAME . ' in zm.conf, but no corresponding entry found in Servers table.');
|
||||
} else {
|
||||
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
|
||||
}
|
||||
} else if ( defined('ZM_SERVER_HOST') and ZM_SERVER_HOST ) {
|
||||
$Server = $ServerModel->find( 'first', array( 'conditions'=>array('Name'=>ZM_SERVER_HOST) ) );
|
||||
if ( ! $Server ) {
|
||||
Error('Invalid Multi-Server configration detected. ZM_SERVER_HOST set to ' . ZM_SERVER_HOST . ' in zm.conf, but no corresponding entry found in Servers table.');
|
||||
} else {
|
||||
define( 'ZM_SERVER_ID', $Server['Server']['Id'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -434,14 +434,11 @@ class EventsController extends AppController {
|
|||
// Find the max Frame for this Event. Error out otherwise.
|
||||
$this->loadModel('Frame');
|
||||
|
||||
if (! $frame = $this->Frame->find('first', array(
|
||||
$frame = $this->Frame->find('first', array(
|
||||
'conditions' => array(
|
||||
'EventId' => $event['Event']['Id'],
|
||||
'Score' => $event['Event']['MaxScore']
|
||||
)
|
||||
))) {
|
||||
throw new NotFoundException(__('Can not find Frame for Event ' . $event['Event']['Id']));
|
||||
}
|
||||
return $frame['Frame']['Id'];
|
||||
'EventId' => $event['Event']['Id'],
|
||||
'Score' => $event['Event']['MaxScore']
|
||||
)));
|
||||
return empty($frame)?null:$frame['Frame']['Id'];
|
||||
}
|
||||
} // end class EventsController
|
||||
|
|
|
@ -14,6 +14,18 @@ class UsersController extends AppController {
|
|||
*/
|
||||
public $components = array('RequestHandler', 'Paginator');
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
|
||||
global $user;
|
||||
# We already tested for auth in appController, so we just need to test for specific permission
|
||||
$canView = (!$user) || ($user['System'] != 'None');
|
||||
if ( !$canView ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* index method
|
||||
*
|
||||
|
@ -23,6 +35,12 @@ class UsersController extends AppController {
|
|||
public function index() {
|
||||
$this->User->recursive = 0;
|
||||
|
||||
global $user;
|
||||
# We should actually be able to list our own user, but I'm not bothering at this time.
|
||||
if ( $user['System'] == 'None' ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
$users = $this->Paginator->paginate('User');
|
||||
|
||||
$this->set(compact('users'));
|
||||
|
@ -36,16 +54,20 @@ class UsersController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function view($id = null) {
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
|
||||
));
|
||||
|
||||
$this->User->recursive = 1;
|
||||
if (!$this->User->exists($id)) {
|
||||
|
||||
global $user;
|
||||
# We can view ourselves
|
||||
$canView = ($user['System'] != 'None') or ($user['Id'] == $id);
|
||||
if ( !$canView ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !$this->User->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid user'));
|
||||
}
|
||||
|
||||
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
|
||||
$user = $this->User->find('first', $options);
|
||||
|
||||
|
@ -61,9 +83,16 @@ class UsersController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
if ($this->request->is('post')) {
|
||||
if ( $this->request->is('post') ) {
|
||||
|
||||
global $user;
|
||||
if ( $user['System'] != 'Edit' ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->User->create();
|
||||
if ($this->User->save($this->request->data)) {
|
||||
if ( $this->User->save($this->request->data) ) {
|
||||
return $this->flash(__('The user has been saved.'), array('action' => 'index'));
|
||||
}
|
||||
$this->Session->setFlash(
|
||||
|
@ -82,20 +111,29 @@ class UsersController extends AppController {
|
|||
public function edit($id = null) {
|
||||
$this->User->id = $id;
|
||||
|
||||
if (!$this->User->exists($id)) {
|
||||
global $user;
|
||||
$canEdit = ($user['System'] == 'Edit') or (($user['Id'] == $id) and ZM_USER_SELF_EDIT);
|
||||
if ( !$canEdit ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !$this->User->exists($id) ) {
|
||||
throw new NotFoundException(__('Invalid user'));
|
||||
}
|
||||
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
if ($this->User->save($this->request->data)) {
|
||||
if ( $this->request->is('post') || $this->request->is('put') ) {
|
||||
if ( $this->User->save($this->request->data) ) {
|
||||
$message = 'Saved';
|
||||
} else {
|
||||
$message = 'Error';
|
||||
}
|
||||
} else {
|
||||
$this->request->data = $this->User->read(null, $id);
|
||||
unset($this->request->data['User']['password']);
|
||||
}
|
||||
# What is this doing? Resetting the request data? I understand clearing the password field
|
||||
# but generally I feel like the request data should be read only
|
||||
$this->request->data = $this->User->read(null, $id);
|
||||
unset($this->request->data['User']['Password']);
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
|
@ -112,11 +150,18 @@ class UsersController extends AppController {
|
|||
*/
|
||||
public function delete($id = null) {
|
||||
$this->User->id = $id;
|
||||
if (!$this->User->exists()) {
|
||||
|
||||
global $user;
|
||||
# Can't delete ourselves
|
||||
if ( ($user['System'] != 'Edit') or ($user['Id'] == $id) ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
if ( !$this->User->exists() ) {
|
||||
throw new NotFoundException(__('Invalid user'));
|
||||
}
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
if ($this->User->delete()) {
|
||||
if ( $this->User->delete() ) {
|
||||
$message = 'The user has been deleted.';
|
||||
} else {
|
||||
$message = 'The user could not be deleted. Please, try again.';
|
||||
|
@ -126,47 +171,4 @@ class UsersController extends AppController {
|
|||
'_serialize' => array('message')
|
||||
));
|
||||
}
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
|
||||
));
|
||||
if ( $configs['ZM_OPT_USE_AUTH'] ) {
|
||||
$this->Auth->allow('add','logout');
|
||||
} else {
|
||||
$this->Auth->allow();
|
||||
}
|
||||
}
|
||||
|
||||
public function login() {
|
||||
$this->loadModel('Config');
|
||||
$configs = $this->Config->find('list', array(
|
||||
'fields' => array('Name', 'Value'),
|
||||
'conditions' => array('Name' => array('ZM_OPT_USE_AUTH'))
|
||||
));
|
||||
|
||||
if ( ! $configs['ZM_OPT_USE_AUTH'] ) {
|
||||
$this->set(array(
|
||||
'message' => 'Login is not required.',
|
||||
'_serialize' => array('message')
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
if ($this->Auth->login()) {
|
||||
return $this->redirect($this->Auth->redirectUrl());
|
||||
}
|
||||
$this->Session->setFlash(__('Invalid username or password, try again'));
|
||||
}
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
return $this->redirect($this->Auth->logout());
|
||||
}
|
||||
|
||||
}
|
||||
} # end class UsersController
|
||||
|
|
|
@ -40,6 +40,7 @@ class ZonesController extends AppController {
|
|||
'_serialize' => array('zones')
|
||||
));
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$this->Zone->recursive = -1;
|
||||
|
||||
|
@ -63,23 +64,43 @@ class ZonesController extends AppController {
|
|||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
if ( $this->request->is('post') ) {
|
||||
|
||||
global $user;
|
||||
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
|
||||
if ( !$canEdit ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
if ( !$this->request->is('post') ) {
|
||||
throw new BadRequestException(__('Invalid method. Should be post'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->Zone->create();
|
||||
if ( $this->Zone->save($this->request->data) ) {
|
||||
return $this->flash(__('The zone has been saved.'), array('action' => 'index'));
|
||||
global $user;
|
||||
$canEdit = (!$user) || $user['Monitors'] == 'Edit';
|
||||
if ( !$canEdit ) {
|
||||
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||
return;
|
||||
}
|
||||
|
||||
$zone = null;
|
||||
|
||||
$this->Zone->create();
|
||||
$zone = $this->Zone->save($this->request->data);
|
||||
if ( $zone ) {
|
||||
require_once __DIR__ .'/../../../includes/Monitor.php';
|
||||
$monitor = new ZM\Monitor($zone['Zone']['MonitorId']);
|
||||
$monitor->zmaControl('restart');
|
||||
$message = 'Saved';
|
||||
//$zone = $this->Zone->find('first', array('conditions' => array( array('Zone.' . $this->Zone->primaryKey => $this->Zone),
|
||||
} else {
|
||||
$message = 'Error: ';
|
||||
// if there is a validation message, use it
|
||||
if ( !$this->Zone->validates() ) {
|
||||
$message = $this->Zone->validationErrors;
|
||||
}
|
||||
}
|
||||
$monitors = $this->Zone->Monitor->find('list');
|
||||
$this->set(compact('monitors'));
|
||||
}
|
||||
|
||||
$this->set(array(
|
||||
'message' => $message,
|
||||
'zone' => $zone,
|
||||
'_serialize' => array('message','zone')
|
||||
));
|
||||
} // end function add()
|
||||
|
||||
/**
|
||||
* edit method
|
||||
|
|
|
@ -3,8 +3,6 @@ App::uses('AppModel', 'Model');
|
|||
/**
|
||||
* User Model
|
||||
*
|
||||
* @property Monitor $Monitor
|
||||
* @property Frame $Frame
|
||||
*/
|
||||
class User extends AppModel {
|
||||
|
||||
|
@ -23,6 +21,20 @@ class User extends AppModel {
|
|||
)
|
||||
);
|
||||
|
||||
function beforeFind($query) {
|
||||
if ( empty($query['fields']) ) {
|
||||
$schema = $this->schema();
|
||||
unset($schema['Password']);
|
||||
|
||||
foreach (array_keys($schema) as $field) {
|
||||
$query['fields'][] = $this->alias . '.' . $field;
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
return parent::beforeFind($query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use table
|
||||
*
|
||||
|
@ -53,14 +65,6 @@ class User extends AppModel {
|
|||
* @var array
|
||||
*/
|
||||
public $belongsTo = array(
|
||||
/*'Monitor' => array(
|
||||
'className' => 'Monitor',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => ''
|
||||
)
|
||||
*/
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -69,21 +73,6 @@ class User extends AppModel {
|
|||
* @var array
|
||||
*/
|
||||
public $hasMany = array(
|
||||
/*
|
||||
'Frame' => array(
|
||||
'className' => 'Frame',
|
||||
'foreignKey' => 'UserId',
|
||||
'dependent' => true,
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => '',
|
||||
'limit' => '',
|
||||
'offset' => '',
|
||||
'exclusive' => '',
|
||||
'finderQuery' => '',
|
||||
'counterQuery' => ''
|
||||
)
|
||||
*/
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,32 @@ class Zone extends AppModel {
|
|||
|
||||
public $recursive = -1;
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $validate = array(
|
||||
'MonitorId' => array(
|
||||
'rule' => 'checkMonitorId',
|
||||
//array('naturalNumber'),
|
||||
'message' => 'Zones must have a valid MonitorId',
|
||||
'allowEmpty' => false,
|
||||
'required' => true,
|
||||
//'last' => false, // Stop validation after this rule
|
||||
//'on' => 'create', // Limit validation to 'create' or 'update' operations
|
||||
),
|
||||
'Name' => array(
|
||||
'required' => array(
|
||||
//'on' => 'create',
|
||||
'rule' => 'notBlank',
|
||||
'message' => 'Zone Name must be specified for creation',
|
||||
'required' => true,
|
||||
),
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
//The Associations below have been created with all possible keys, those that are not needed can be removed
|
||||
|
||||
/**
|
||||
|
@ -41,9 +67,17 @@ class Zone extends AppModel {
|
|||
'Monitor' => array(
|
||||
'className' => 'Monitor',
|
||||
'foreignKey' => 'MonitorId',
|
||||
'conditions' => '',
|
||||
'fields' => '',
|
||||
'order' => ''
|
||||
//'conditions' => '',
|
||||
//'fields' => '',
|
||||
//'order' => ''
|
||||
)
|
||||
);
|
||||
|
||||
public function checkMonitorId($data) {
|
||||
if ( !$this->Monitor->find('first', array('conditions'=>array('Id'=>$data['MonitorId']))) ) {
|
||||
//$this->invalidate('MonitorId', 'Invalid Monitor Id');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
echo json_encode($message);
|
||||
echo json_encode($zone);
|
|
@ -0,0 +1,2 @@
|
|||
echo json_encode($message);
|
||||
echo json_encode($zone);
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response'=>$message, 'zone'=>$zone));
|
||||
echo $xml->asXML();
|
|
@ -0,0 +1,2 @@
|
|||
$xml = Xml::fromArray(array('response' => $message, 'zone'=>$zone));
|
||||
echo $xml->asXML();
|
|
@ -262,13 +262,18 @@ class Event extends ZM_Object {
|
|||
return $streamSrc;
|
||||
} // end function getStreamSrc
|
||||
|
||||
# The new='' is to so that if we pass null, we reset the value of DiskSpace.
|
||||
# '' is not a valid DiskSpace so that tells us that nothing was passed whereas null (unknown) is.
|
||||
function DiskSpace( $new='' ) {
|
||||
if ( is_null($new) or ( $new != '' ) ) {
|
||||
$this->{'DiskSpace'} = $new;
|
||||
}
|
||||
if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
|
||||
$this->{'DiskSpace'} = folder_size($this->Path());
|
||||
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
|
||||
if ( $this->{'EndTime'} ) {
|
||||
# Finished events shouldn't grow in size much so we can commit it to the db.
|
||||
dbQuery('UPDATE Events SET DiskSpace=? WHERE Id=?', array($this->{'DiskSpace'}, $this->{'Id'}));
|
||||
}
|
||||
}
|
||||
return $this->{'DiskSpace'};
|
||||
}
|
||||
|
@ -380,54 +385,54 @@ class Event extends ZM_Object {
|
|||
$Event = $this;
|
||||
$eventPath = $Event->Path();
|
||||
|
||||
if ( $frame and ! is_array($frame) ) {
|
||||
if ( $frame and !is_array($frame) ) {
|
||||
# Must be an Id
|
||||
Logger::Debug("Assuming that $frame is an Id");
|
||||
$frame = array( 'FrameId'=>$frame, 'Type'=>'', 'Delta'=>0 );
|
||||
$frame = array('FrameId'=>$frame, 'Type'=>'', 'Delta'=>0);
|
||||
}
|
||||
|
||||
if ( ( ! $frame ) and file_exists($eventPath.'/snapshot.jpg') ) {
|
||||
if ( ( !$frame ) and file_exists($eventPath.'/snapshot.jpg') ) {
|
||||
# No frame specified, so look for a snapshot to use
|
||||
$captImage = 'snapshot.jpg';
|
||||
Logger::Debug("Frame not specified, using snapshot");
|
||||
$frame = array('FrameId'=>'snapshot', 'Type'=>'','Delta'=>0);
|
||||
Logger::Debug('Frame not specified, using snapshot');
|
||||
$frame = array('FrameId'=>'snapshot', 'Type'=>'', 'Delta'=>0);
|
||||
} else {
|
||||
$captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyze.jpg', $frame['FrameId'] );
|
||||
$captImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyze.jpg', $frame['FrameId']);
|
||||
if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
|
||||
$captImage = sprintf( '%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId'] );
|
||||
if ( ! file_exists( $eventPath.'/'.$captImage ) ) {
|
||||
$captImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-capture.jpg', $frame['FrameId']);
|
||||
if ( !file_exists($eventPath.'/'.$captImage) ) {
|
||||
# Generate the frame JPG
|
||||
if ( $Event->DefaultVideo() ) {
|
||||
$videoPath = $eventPath.'/'.$Event->DefaultVideo();
|
||||
|
||||
if ( ! file_exists( $videoPath ) ) {
|
||||
Error("Event claims to have a video file, but it does not seem to exist at $videoPath" );
|
||||
if ( !file_exists($videoPath) ) {
|
||||
Error('Event claims to have a video file, but it does not seem to exist at '.$videoPath);
|
||||
return '';
|
||||
}
|
||||
|
||||
#$command ='ffmpeg -v 0 -i '.$videoPath.' -vf "select=gte(n\\,'.$frame['FrameId'].'),setpts=PTS-STARTPTS" '.$eventPath.'/'.$captImage;
|
||||
$command ='ffmpeg -ss '. $frame['Delta'] .' -i '.$videoPath.' -frames:v 1 '.$eventPath.'/'.$captImage;
|
||||
Logger::Debug( "Running $command" );
|
||||
Logger::Debug('Running '.$command);
|
||||
$output = array();
|
||||
$retval = 0;
|
||||
exec( $command, $output, $retval );
|
||||
exec($command, $output, $retval);
|
||||
Logger::Debug("Retval: $retval, output: " . implode("\n", $output));
|
||||
} else {
|
||||
Error("Can't create frame images from video because there is no video file for event ".$Event->Id().' at ' .$Event->Path() );
|
||||
Error('Can\'t create frame images from video because there is no video file for event '.$Event->Id().' at ' .$Event->Path());
|
||||
}
|
||||
} // end if capture file exists
|
||||
} // end if analyze file exists
|
||||
} // end if frame or snapshot
|
||||
|
||||
$captPath = $eventPath.'/'.$captImage;
|
||||
if ( ! file_exists($captPath) ) {
|
||||
Error("Capture file does not exist at $captPath");
|
||||
if ( !file_exists($captPath) ) {
|
||||
Error('Capture file does not exist at '.$captPath);
|
||||
}
|
||||
|
||||
$analImage = sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d-analyse.jpg', $frame['FrameId']);
|
||||
$analPath = $eventPath.'/'.$analImage;
|
||||
|
||||
$alarmFrame = $frame['Type']=='Alarm';
|
||||
$alarmFrame = $frame['Type'] == 'Alarm';
|
||||
|
||||
$hasAnalImage = $alarmFrame && file_exists($analPath) && filesize($analPath);
|
||||
$isAnalImage = $hasAnalImage && !$captureOnly;
|
||||
|
@ -443,8 +448,8 @@ class Event extends ZM_Object {
|
|||
$fraction = sprintf('%.3f', $scale/SCALE_BASE);
|
||||
$scale = (int)round($scale);
|
||||
|
||||
$thumbCaptPath = preg_replace( '/\.jpg$/', "-$scale.jpg", $captPath );
|
||||
$thumbAnalPath = preg_replace( '/\.jpg$/', "-$scale.jpg", $analPath );
|
||||
$thumbCaptPath = preg_replace('/\.jpg$/', "-$scale.jpg", $captPath);
|
||||
$thumbAnalPath = preg_replace('/\.jpg$/', "-$scale.jpg", $analPath);
|
||||
|
||||
if ( $isAnalImage ) {
|
||||
$imagePath = $analPath;
|
||||
|
@ -457,7 +462,7 @@ class Event extends ZM_Object {
|
|||
$thumbFile = $thumbPath;
|
||||
if ( $overwrite || ! file_exists($thumbFile) || ! filesize($thumbFile) ) {
|
||||
// Get new dimensions
|
||||
list( $imageWidth, $imageHeight ) = getimagesize($imagePath);
|
||||
list($imageWidth, $imageHeight) = getimagesize($imagePath);
|
||||
$thumbWidth = $imageWidth * $fraction;
|
||||
$thumbHeight = $imageHeight * $fraction;
|
||||
|
||||
|
@ -484,7 +489,7 @@ class Event extends ZM_Object {
|
|||
);
|
||||
|
||||
return $imageData;
|
||||
}
|
||||
} # getImageSrc
|
||||
|
||||
public function link_to($text=null) {
|
||||
if ( !$text )
|
||||
|
|
|
@ -19,9 +19,9 @@ class Group extends ZM_Object {
|
|||
|
||||
public function delete() {
|
||||
if ( property_exists($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'}));
|
||||
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']);
|
||||
|
@ -47,7 +47,7 @@ class Group extends ZM_Object {
|
|||
|
||||
public function MonitorIds( ) {
|
||||
if ( ! property_exists($this, 'MonitorIds') ) {
|
||||
$this->{'MonitorIds'} = dbFetchAll('SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($this->{'Id'}));
|
||||
$this->{'MonitorIds'} = dbFetchAll('SELECT `MonitorId` FROM `Groups_Monitors` WHERE `GroupId`=?', 'MonitorId', array($this->{'Id'}));
|
||||
}
|
||||
return $this->{'MonitorIds'};
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class Group extends ZM_Object {
|
|||
session_write_close();
|
||||
}
|
||||
|
||||
return htmlSelect( 'GroupId[]', Group::get_dropdown_options(), isset($_SESSION['GroupId'])?$_SESSION['GroupId']:null, array(
|
||||
return htmlSelect('GroupId[]', Group::get_dropdown_options(), isset($_SESSION['GroupId'])?$_SESSION['GroupId']:null, array(
|
||||
'data-on-change' => 'submitThisForm',
|
||||
'class'=>'chosen',
|
||||
'multiple'=>'multiple',
|
||||
|
|
|
@ -201,6 +201,11 @@ class Monitor extends ZM_Object {
|
|||
if ( ZM_RAND_STREAM ) {
|
||||
$args['rand'] = time();
|
||||
}
|
||||
foreach ( array('scale') as $int_arg ) {
|
||||
if ( isset($args[$int_arg]) and (!is_numeric($args[$int_arg]) or !$args[$int_arg] ) ) {
|
||||
unset($args[$int_arg]);
|
||||
}
|
||||
}
|
||||
|
||||
$streamSrc .= '?'.http_build_query($args, '', $querySep);
|
||||
|
||||
|
@ -293,12 +298,12 @@ class Monitor extends ZM_Object {
|
|||
return;
|
||||
}
|
||||
}
|
||||
Logger::Debug("sending command to $url");
|
||||
Logger::Debug('sending command to '.$url);
|
||||
|
||||
$context = stream_context_create();
|
||||
try {
|
||||
$result = file_get_contents($url, false, $context);
|
||||
if ($result === FALSE) { /* Handle error */
|
||||
if ( $result === FALSE ) { /* Handle error */
|
||||
Error("Error restarting zmc using $url");
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
|
@ -310,14 +315,15 @@ class Monitor extends ZM_Object {
|
|||
} // end function zmcControl
|
||||
|
||||
function zmaControl($mode=false) {
|
||||
if ( ! $this->{'Id'} ) {
|
||||
if ( !$this->{'Id'} ) {
|
||||
Warning('Attempt to control a monitor with no Id');
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (!defined('ZM_SERVER_ID')) or ( property_exists($this, 'ServerId') and (ZM_SERVER_ID==$this->{'ServerId'}) ) ) {
|
||||
if ( $this->{'Function'} == 'None' || $this->{'Function'} == 'Monitor' || $mode == 'stop' ) {
|
||||
if ( ZM_OPT_CONTROL ) {
|
||||
if ( ZM_OPT_CONTROL && $this->Controllable() && $this->TrackMotion() &&
|
||||
( $this->{'Function'} == 'Modect' || $this->{'Function'} == 'Mocord' ) ) {
|
||||
daemonControl('stop', 'zmtrack.pl', '-m '.$this->{'Id'});
|
||||
}
|
||||
daemonControl('stop', 'zma', '-m '.$this->{'Id'});
|
||||
|
@ -340,7 +346,7 @@ class Monitor extends ZM_Object {
|
|||
} else if ( $this->ServerId() ) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$mode.'/zma.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
|
@ -354,10 +360,10 @@ class Monitor extends ZM_Object {
|
|||
}
|
||||
Logger::Debug("sending command to $url");
|
||||
|
||||
$context = stream_context_create();
|
||||
$context = stream_context_create();
|
||||
try {
|
||||
$result = file_get_contents($url, false, $context);
|
||||
if ($result === FALSE) { /* Handle error */
|
||||
if ( $result === FALSE ) { /* Handle error */
|
||||
Error("Error restarting zma using $url");
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
|
@ -490,12 +496,11 @@ class Monitor extends ZM_Object {
|
|||
foreach ( explode(' ', $command) as $option ) {
|
||||
if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
|
||||
$options[$matches[1]] = $matches[2]?$matches[2]:1;
|
||||
} else if ( $option != '' and $option != 'quit' ) {
|
||||
} else if ( $option != '' and $option != 'quit' and $option != 'start' and $option != 'stop' ) {
|
||||
Warning("Ignored command for zmcontrol $option in $command");
|
||||
}
|
||||
}
|
||||
if ( !count($options) ) {
|
||||
|
||||
if ( $command == 'quit' or $command == 'start' or $command == 'stop' ) {
|
||||
# These are special as we now run zmcontrol as a daemon through zmdc.
|
||||
$status = daemonStatus('zmcontrol.pl', array('--id', $this->{'Id'}));
|
||||
|
@ -539,7 +544,7 @@ class Monitor extends ZM_Object {
|
|||
} else if ( $this->ServerId() ) {
|
||||
$Server = $this->Server();
|
||||
|
||||
$url = ZM_BASE_PROTOCOL . '://'.$Server->Hostname().'/zm/api/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
|
||||
$url = $Server->UrlToApi().'/monitors/daemonControl/'.$this->{'Id'}.'/'.$command.'/zmcontrol.pl.json';
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
|
|
|
@ -306,7 +306,7 @@ class ZM_Object {
|
|||
$fields = array_keys($fields);
|
||||
|
||||
if ( $this->Id() ) {
|
||||
$sql = 'UPDATE '.$table.' SET '.implode(', ', array_map(function($field) {return '`'.$field.'`=?';}, $fields)).' WHERE Id=?';
|
||||
$sql = 'UPDATE `'.$table.'` SET '.implode(', ', array_map(function($field) {return '`'.$field.'`=?';}, $fields)).' WHERE Id=?';
|
||||
$values = array_map(function($field){ return $this->{$field};}, $fields);
|
||||
$values[] = $this->{'Id'};
|
||||
if ( dbQuery($sql, $values) )
|
||||
|
@ -314,8 +314,8 @@ class ZM_Object {
|
|||
} else {
|
||||
unset($fields['Id']);
|
||||
|
||||
$sql = 'INSERT INTO '.$table.
|
||||
' ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
||||
$sql = 'INSERT INTO `'.$table.
|
||||
'` ('.implode(', ', array_map(function($field) {return '`'.$field.'`';}, $fields)).
|
||||
') VALUES ('.
|
||||
implode(', ', array_map(function($field){return '?';}, $fields)).')';
|
||||
|
||||
|
@ -331,7 +331,7 @@ class ZM_Object {
|
|||
public function delete() {
|
||||
$class = get_class($this);
|
||||
$table = $class::$table;
|
||||
dbQuery("DELETE FROM $table WHERE Id=?", array($this->{'Id'}));
|
||||
dbQuery("DELETE FROM `$table` WHERE Id=?", array($this->{'Id'}));
|
||||
if ( isset($object_cache[$class]) and isset($object_cache[$class][$this->{'Id'}]) )
|
||||
unset($object_cache[$class][$this->{'Id'}]);
|
||||
}
|
||||
|
|
|
@ -85,8 +85,6 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
|||
// We update the request id so that the newly saved filter is auto-selected
|
||||
$_REQUEST['Id'] = $filter->Id();
|
||||
}
|
||||
if ( $filter->Background() )
|
||||
$filter->control('start');
|
||||
|
||||
if ( $action == 'execute' ) {
|
||||
$filter->execute();
|
||||
|
@ -94,6 +92,8 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
|
|||
$filter->delete();
|
||||
|
||||
$view = 'events';
|
||||
} else if ( $filter->Background() ) {
|
||||
$filter->control('start');
|
||||
}
|
||||
|
||||
} else if ( $action == 'control' ) {
|
||||
|
|
|
@ -18,27 +18,36 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
|
||||
if ( $action == 'user' ) {
|
||||
if ( $action == 'Save' ) {
|
||||
if ( canEdit('System') ) {
|
||||
if ( !empty($_REQUEST['uid']) )
|
||||
if ( !empty($_REQUEST['uid']) ) {
|
||||
$dbUser = dbFetchOne('SELECT * FROM Users WHERE Id=?', NULL, array($_REQUEST['uid']));
|
||||
else
|
||||
} else {
|
||||
$dbUser = array();
|
||||
}
|
||||
|
||||
$types = array();
|
||||
if ( isset($_REQUEST['newUser']['MonitorIds']) and is_array($_REQUEST['newUser']['MonitorIds']) )
|
||||
$_REQUEST['newUser']['MonitorIds'] = implode(',', $_REQUEST['newUser']['MonitorIds']);
|
||||
if ( !$_REQUEST['newUser']['Password'] )
|
||||
unset($_REQUEST['newUser']['Password']);
|
||||
|
||||
$changes = getFormChanges($dbUser, $_REQUEST['newUser'], $types);
|
||||
|
||||
if ( function_exists('password_hash') ) {
|
||||
$pass_hash = '"'.password_hash($_REQUEST['newUser']['Password'], PASSWORD_BCRYPT).'"';
|
||||
} else {
|
||||
$pass_hash = ' PASSWORD('.dbEscape($_REQUEST['newUser']['Password']).') ';
|
||||
ZM\Info('Cannot use bcrypt as you are using PHP < 5.3');
|
||||
}
|
||||
|
||||
if ( $_REQUEST['newUser']['Password'] ) {
|
||||
$changes['Password'] = 'Password = '.$pass_hash;
|
||||
} else {
|
||||
unset($changes['Password']);
|
||||
|
||||
if ( isset($_REQUEST['newUser']['Password']) ) {
|
||||
if ( function_exists('password_hash') ) {
|
||||
$pass_hash = '"'.password_hash($_REQUEST['newUser']['Password'], PASSWORD_BCRYPT).'"';
|
||||
} else {
|
||||
$pass_hash = ' PASSWORD('.dbEscape($_REQUEST['newUser']['Password']).') ';
|
||||
ZM\Info('Cannot use bcrypt as you are using PHP < 5.3');
|
||||
}
|
||||
|
||||
if ( $_REQUEST['newUser']['Password'] ) {
|
||||
$changes['Password'] = 'Password = '.$pass_hash;
|
||||
} else {
|
||||
unset($changes['Password']);
|
||||
}
|
||||
}
|
||||
|
||||
if ( count($changes) ) {
|
||||
|
|
|
@ -260,6 +260,22 @@ function userFromSession() {
|
|||
return $user;
|
||||
}
|
||||
|
||||
function get_auth_relay() {
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( ZM_AUTH_RELAY == 'hashed' ) {
|
||||
return 'auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
|
||||
} else if ( ZM_AUTH_RELAY == 'plain' ) {
|
||||
// password probably needs to be escaped
|
||||
return 'username='.$_SESSION['username'].'&password='.urlencode($_SESSION['password']);
|
||||
} else if ( ZM_AUTH_RELAY == 'none' ) {
|
||||
return 'username='.$_SESSION['username'];
|
||||
} else {
|
||||
ZM\Error('Unknown value for ZM_AUTH_RELAY ' . ZM_AUTH_RELAY);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
} // end function get_auth_relay
|
||||
|
||||
if ( ZM_OPT_USE_AUTH ) {
|
||||
if ( !empty($_REQUEST['token']) ) {
|
||||
// we only need to get the username here
|
||||
|
|
|
@ -389,7 +389,7 @@ function csrf_conf($key, $val) {
|
|||
*/
|
||||
function csrf_start() {
|
||||
if ($GLOBALS['csrf']['auto-session'] && !session_id()) {
|
||||
session_start();
|
||||
zm_session_start();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,20 +25,26 @@ define('DB_LOG_DEBUG', 2);
|
|||
$GLOBALS['dbLogLevel'] = DB_LOG_OFF;
|
||||
|
||||
$GLOBALS['dbConn'] = false;
|
||||
require_once('logger.php');
|
||||
|
||||
function dbConnect() {
|
||||
global $dbConn;
|
||||
|
||||
if ( strpos(ZM_DB_HOST, ':') ) {
|
||||
// Host variable may carry a port or socket.
|
||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||
if ( ctype_digit($portOrSocket) ) {
|
||||
$socket = ':host='.$host . ';port='.$portOrSocket;
|
||||
$socket = '';
|
||||
if ( ZM_DB_HOST ) {
|
||||
if ( strpos(ZM_DB_HOST, ':') ) {
|
||||
// Host variable may carry a port or socket.
|
||||
list($host, $portOrSocket) = explode(':', ZM_DB_HOST, 2);
|
||||
if ( ctype_digit($portOrSocket) ) {
|
||||
$socket = ':host='.$host . ';port='.$portOrSocket.';';
|
||||
} else {
|
||||
$socket = ':unix_socket='.$portOrSocket.';';
|
||||
}
|
||||
} else {
|
||||
$socket = ':unix_socket='.$portOrSocket;
|
||||
$socket = ':host='.ZM_DB_HOST.';';
|
||||
}
|
||||
} else {
|
||||
$socket = ':host='.ZM_DB_HOST;
|
||||
$socket = ':host=localhost;';
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -49,9 +55,9 @@ function dbConnect() {
|
|||
PDO::MYSQL_ATTR_SSL_KEY => ZM_DB_SSL_CLIENT_KEY,
|
||||
PDO::MYSQL_ATTR_SSL_CERT => ZM_DB_SSL_CLIENT_CERT,
|
||||
);
|
||||
$dbConn = new PDO(ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS, $dbOptions);
|
||||
$dbConn = new PDO(ZM_DB_TYPE.$socket.'dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS, $dbOptions);
|
||||
} else {
|
||||
$dbConn = new PDO(ZM_DB_TYPE . $socket . ';dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS);
|
||||
$dbConn = new PDO(ZM_DB_TYPE.$socket.'dbname='.ZM_DB_NAME, ZM_DB_USER, ZM_DB_PASS);
|
||||
}
|
||||
|
||||
$dbConn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
|
@ -61,9 +67,12 @@ function dbConnect() {
|
|||
error_log('Unable to connect to ZM DB ' . $ex->getMessage());
|
||||
$dbConn = null;
|
||||
}
|
||||
}
|
||||
return $dbConn;
|
||||
} // end function dbConnect
|
||||
|
||||
dbConnect();
|
||||
if ( !dbConnect() ) {
|
||||
ZM\Fatal("Failed db connection to $socket");
|
||||
}
|
||||
|
||||
function dbDisconnect() {
|
||||
global $dbConn;
|
||||
|
|
|
@ -40,7 +40,7 @@ function CSPHeaders($view, $nonce) {
|
|||
if ( ! $Servers )
|
||||
$Servers = ZM\Server::find();
|
||||
|
||||
$additionalScriptSrc = implode(' ', array_map(function($S){return $S->Url();}, $Servers));
|
||||
$additionalScriptSrc = implode(' ', array_map(function($S){return $S->Hostname();}, $Servers));
|
||||
switch ($view) {
|
||||
case 'login': {
|
||||
if (defined('ZM_OPT_USE_GOOG_RECAPTCHA')
|
||||
|
@ -840,9 +840,15 @@ function daemonStatus($daemon, $args=false) {
|
|||
initDaemonStatus();
|
||||
|
||||
$string = $daemon;
|
||||
if ( $args )
|
||||
$string .= ' ' . $args;
|
||||
return( strpos($daemon_status, "'$string' running") !== false );
|
||||
if ( $args ) {
|
||||
if ( is_array($args) ) {
|
||||
$string .= join(' ', $args);
|
||||
ZM\Warning("daemonStatus args: $string");
|
||||
} else {
|
||||
$string .= ' ' . $args;
|
||||
}
|
||||
}
|
||||
return ( strpos($daemon_status, "'$string' running") !== false );
|
||||
}
|
||||
|
||||
function zmcStatus($monitor) {
|
||||
|
@ -1484,15 +1490,15 @@ function getLoad() {
|
|||
function getDiskPercent($path = ZM_DIR_EVENTS) {
|
||||
$total = disk_total_space($path);
|
||||
if ( $total === false ) {
|
||||
Error('disk_total_space returned false. Verify the web account user has access to ' . $path);
|
||||
ZM\Error('disk_total_space returned false. Verify the web account user has access to ' . $path);
|
||||
return 0;
|
||||
} elseif ( $total == 0 ) {
|
||||
Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path);
|
||||
ZM\Error('disk_total_space indicates the following path has a filesystem size of zero bytes ' . $path);
|
||||
return 100;
|
||||
}
|
||||
$free = disk_free_space($path);
|
||||
if ( $free === false ) {
|
||||
Error('disk_free_space returned false. Verify the web account user has access to ' . $path);
|
||||
ZM\Error('disk_free_space returned false. Verify the web account user has access to ' . $path);
|
||||
}
|
||||
$space = round((($total - $free) / $total) * 100);
|
||||
return $space;
|
||||
|
@ -2048,7 +2054,7 @@ function logState() {
|
|||
if ( $count['Level'] <= ZM\Logger::PANIC )
|
||||
$count['Level'] = ZM\Logger::FATAL;
|
||||
if ( !($levelCount = $levelCounts[$count['Level']]) ) {
|
||||
Error('Unexpected Log level '.$count['Level']);
|
||||
ZM\Error('Unexpected Log level '.$count['Level']);
|
||||
next;
|
||||
}
|
||||
if ( $levelCount[1] && $count['LevelCount'] >= $levelCount[1] ) {
|
||||
|
@ -2075,18 +2081,23 @@ function isVector(&$array) {
|
|||
|
||||
function checkJsonError($value) {
|
||||
if ( function_exists('json_last_error') ) {
|
||||
$value = var_export($value,true);
|
||||
switch( json_last_error() ) {
|
||||
$value = var_export($value, true);
|
||||
switch ( json_last_error() ) {
|
||||
case JSON_ERROR_DEPTH :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', maximum stack depth exceeded");
|
||||
ZM\Error("Unable to decode JSON string '$value', maximum stack depth exceeded");
|
||||
break;
|
||||
case JSON_ERROR_CTRL_CHAR :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', unexpected control character found");
|
||||
ZM\Error("Unable to decode JSON string '$value', unexpected control character found");
|
||||
break;
|
||||
case JSON_ERROR_STATE_MISMATCH :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', invalid or malformed JSON");
|
||||
ZM\Error("Unable to decode JSON string '$value', invalid or malformed JSON");
|
||||
break;
|
||||
case JSON_ERROR_SYNTAX :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', syntax error");
|
||||
ZM\Error("Unable to decode JSON string '$value', syntax error");
|
||||
break;
|
||||
default :
|
||||
ZM\Fatal("Unable to decode JSON string '$value', unexpected error ".json_last_error());
|
||||
ZM\Error("Unable to decode JSON string '$value', unexpected error ".json_last_error());
|
||||
break;
|
||||
case JSON_ERROR_NONE:
|
||||
break;
|
||||
}
|
||||
|
@ -2290,7 +2301,8 @@ function validHtmlStr($input) {
|
|||
function getStreamHTML($monitor, $options = array()) {
|
||||
|
||||
if ( isset($options['scale']) ) {
|
||||
if ( $options['scale'] != 'auto' && $options['scale'] != '0' ) {
|
||||
if ( $options['scale'] != 'auto' && $options['scale'] != '0' and $options['scale'] != '' ) {
|
||||
ZM\Logger::Debug("Setting dimensions from scale:".$options['scale']);
|
||||
$options['width'] = reScale($monitor->ViewWidth(), $options['scale']).'px';
|
||||
$options['height'] = reScale($monitor->ViewHeight(), $options['scale']).'px';
|
||||
} else {
|
||||
|
|
|
@ -87,6 +87,7 @@ $SLANG = array(
|
|||
'Actual' => 'Actual',
|
||||
'AddNewControl' => 'Add New Control',
|
||||
'AddNewMonitor' => 'Add',
|
||||
'AddMonitorDisabled' => 'Your user is not allowed to add a new monitor',
|
||||
'AddNewServer' => 'Add New Server',
|
||||
'AddNewStorage' => 'Add New Storage',
|
||||
'AddNewUser' => 'Add New User',
|
||||
|
@ -983,6 +984,18 @@ $OLANG = array(
|
|||
"loglevel=debug" Set verbosity of FFmpeg (quiet, panic, fatal, error, warning, info, verbose, debug)
|
||||
'
|
||||
),
|
||||
'OPTIONS_ENCODER_PARAMETERS' => array(
|
||||
'Help' => '
|
||||
Parameters passed to the encoding codec. name=value separated by either , or newline.~~
|
||||
For example to changing quality, use the crf option. 1 is best, 51 is worst 23 is default.~~
|
||||
~~
|
||||
crf=23~~
|
||||
~~
|
||||
You might want to alter the movflags value to support different behaviours. Some people have troubles viewing videos due to the frag_keyframe option, but that option is supposed to allow viewing of incomplete events. See
|
||||
[https://ffmpeg.org/ffmpeg-formats.html](https://ffmpeg.org/ffmpeg-formats.html)
|
||||
for more information. ZoneMinder\'s default is frag_keyframe,empty_moov~~
|
||||
',
|
||||
),
|
||||
'OPTIONS_DECODERHWACCELNAME' => array(
|
||||
'Help' => '
|
||||
This is equivalent to the ffmpeg -hwaccel command line option. With intel graphics support, use "vaapi". For NVIDIA cuda support use "cuda". To check for support, run ffmpeg -hwaccels on the command line.'
|
||||
|
|
|
@ -509,7 +509,7 @@ th.table-th-sort-rev span.table-th-sort-span {
|
|||
}
|
||||
|
||||
#content {
|
||||
width: 96%;
|
||||
width: 100%;
|
||||
margin: 0 auto 8px auto;
|
||||
line-height: 130%;
|
||||
text-align: center;
|
||||
|
|
|
@ -11,10 +11,30 @@
|
|||
|
||||
textarea,
|
||||
input[name="newMonitor[Name]"],
|
||||
input[name="newMonitor[LabelFormat]"],
|
||||
input[name="newMonitor[ControlDevice]"],
|
||||
input[name="newMonitor[ControlAddress]"] {
|
||||
width: 100%;
|
||||
}
|
||||
input[name="newMonitor[AnalysisFPSLimit]"],
|
||||
input[name="newMonitor[MaxFPS]"],
|
||||
input[name="newMonitor[AlarmMaxFPS]"],
|
||||
input[name="newMonitor[V4LCapturesPerFrame]"]{
|
||||
width: 60px;
|
||||
}
|
||||
input[name="newMonitor[Port]"],
|
||||
input[name="newMonitor[Refresh]"],
|
||||
input[name="newMonitor[LabelX]"],
|
||||
input[name="newMonitor[LabelY]"],
|
||||
input[name="newMonitor[ImageBufferCount]"],
|
||||
input[name="newMonitor[WarmupCount]"],
|
||||
input[name="newMonitor[PreEventCount]"],
|
||||
input[name="newMonitor[PostEventCount]"],
|
||||
input[name="newMonitor[StreamReplayBuffer]"],
|
||||
input[name="newMonitor[AlarmFrameCount]"],
|
||||
input[name="newMonitor[AutoStopTimeout]"],
|
||||
input[name="newMonitor[TrackDelay]"],
|
||||
input[name="newMonitor[ReturnDelay]"],
|
||||
input[name="newMonitor[Width]"],
|
||||
input[name="newMonitor[Height]"] {
|
||||
width: 80px;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue