Merge branch 'master' into filter_pre_post

This commit is contained in:
Isaac Connor 2020-08-13 13:46:35 -04:00
commit 49316244a8
105 changed files with 2093 additions and 575 deletions

View File

@ -3,6 +3,7 @@
module.exports = { module.exports = {
"env": { "env": {
"browser": true, "browser": true,
"es6": true,
}, },
"extends": ["google"], "extends": ["google"],
"overrides": [{ "overrides": [{

View File

@ -32,10 +32,11 @@ install:
- update-binfmts --enable qemu-arm - update-binfmts --enable qemu-arm
env: env:
- SMPFLAGS=-j4 OS=el DIST=7 - SMPFLAGS=-j4 OS=eslint DIST=eslint
- SMPFLAGS=-j4 OS=el DIST=7 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=el DIST=8 DOCKER_REPO=knnniggett/packpack - SMPFLAGS=-j4 OS=el DIST=8 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=fedora DIST=30 - SMPFLAGS=-j4 OS=fedora DIST=31 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=fedora DIST=31 - SMPFLAGS=-j4 OS=fedora DIST=32 DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack - SMPFLAGS=-j4 OS=ubuntu DIST=trusty DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack - SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack - SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack
@ -45,12 +46,6 @@ env:
- SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack - SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack - SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack - SMPFLAGS=-j4 OS=debian DIST=buster DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=trusty ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial ARCH=i386
- SMPFLAGS=-j4 OS=ubuntu DIST=disco ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=buster ARCH=i386
- SMPFLAGS=-j4 OS=debian DIST=stretch ARCH=i386
- SMPFLAGS=-j4 OS=eslint DIST=eslint
compiler: compiler:
- gcc - gcc

View File

@ -899,7 +899,6 @@ configure_file(zmlinkcontent.sh.in "${CMAKE_CURRENT_BINARY_DIR}/zmlinkcontent.sh
# Create a target for man pages # Create a target for man pages
include(Pod2Man) include(Pod2Man)
ADD_MANPAGE_TARGET()
# Process subdirectories # Process subdirectories

View File

@ -53,8 +53,7 @@ MACRO(POD2MAN PODFILE MANFILE SECTION MANPAGE_DEST_PREFIX)
SET(MANPAGE_TARGET "man-${MANFILE}") SET(MANPAGE_TARGET "man-${MANFILE}")
ADD_CUSTOM_TARGET(${MANPAGE_TARGET} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz) ADD_CUSTOM_TARGET(${MANPAGE_TARGET} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz)
ADD_DEPENDENCIES(man ${MANPAGE_TARGET})
INSTALL( INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz FILES ${CMAKE_CURRENT_BINARY_DIR}/${MANFILE}.${SECTION}.gz

View File

@ -46,3 +46,6 @@ ZM_PATH_SWAP=@ZM_TMPDIR@
# Full path to optional arp binary # Full path to optional arp binary
# ZoneMinder will find the arp binary automatically on most systems # ZoneMinder will find the arp binary automatically on most systems
ZM_PATH_ARP="@ZM_PATH_ARP@" ZM_PATH_ARP="@ZM_PATH_ARP@"
#Full path to shutdown binary
ZM_PATH_SHUTDOWN="@ZM_PATH_SHUTDOWN@"

2
db/zm_update-1.35.6.sql Normal file
View File

@ -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);

10
distros/beowulf/NEWS Normal file
View File

@ -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

View File

@ -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

View File

@ -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?).

View File

@ -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

3
distros/beowulf/clean Normal file
View File

@ -0,0 +1,3 @@
.gitattributes
web/api/.gitattributes
web/api/.gitignore

1
distros/beowulf/compat Normal file
View File

@ -0,0 +1 @@
9

View File

@ -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>

166
distros/beowulf/control Normal file
View File

@ -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

174
distros/beowulf/copyright Normal file
View File

@ -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".

View File

@ -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;
}
}

7
distros/beowulf/gbp.conf Normal file
View File

@ -0,0 +1,7 @@
[dch]
id-length = 0
[import-orig]
pristine-tar = False
merge = False

View File

@ -0,0 +1,2 @@
usr/share/man/man3
usr/share/perl5

View File

87
distros/beowulf/rules Executable file
View File

@ -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

View File

@ -0,0 +1 @@
3.0 (quilt)

View File

@ -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

View File

@ -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/*

View File

@ -0,0 +1 @@
docs/_build/html usr/share/doc/zoneminder-doc/

View File

@ -0,0 +1,2 @@
## Convenience symlink:
/usr/share/doc/zoneminder-doc/html /usr/share/doc/zoneminder/html

View File

@ -0,0 +1 @@
conf debian/conf/apache2/zoneminder.conf nginx

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
README.md

View File

@ -0,0 +1,2 @@
debian/examples/*
dbuild/misc/apache.conf

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
/var/tmp /usr/share/zoneminder/www/api/app/tmp

View File

@ -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

View File

@ -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/*

View File

@ -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
}

View File

@ -0,0 +1 @@
rm_conffile /etc/zm/apache.conf 1.28.1-5~

View File

@ -0,0 +1 @@
docs/_build/man/*.1

View File

@ -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#

View File

@ -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#

View File

@ -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#

View File

@ -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

View File

@ -43,6 +43,7 @@ Source0: https://github.com/ZoneMinder/ZoneMinder/archive/%{version}.tar.gz#/zon
Source1: https://github.com/ZoneMinder/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz Source1: https://github.com/ZoneMinder/crud/archive/v%{crud_version}.tar.gz#/crud-%{crud_version}.tar.gz
Source2: https://github.com/ZoneMinder/CakePHP-Enum-Behavior/archive/%{ceb_version}.tar.gz#/cakephp-enum-behavior-%{ceb_version}.tar.gz Source2: https://github.com/ZoneMinder/CakePHP-Enum-Behavior/archive/%{ceb_version}.tar.gz#/cakephp-enum-behavior-%{ceb_version}.tar.gz
%{?rhel:BuildRequires: epel-rpm-macros}
BuildRequires: systemd-devel BuildRequires: systemd-devel
BuildRequires: mariadb-devel BuildRequires: mariadb-devel
BuildRequires: perl-podlators BuildRequires: perl-podlators
@ -206,16 +207,20 @@ mv -f CakePHP-Enum-Behavior-%{ceb_version} ./web/api/app/Plugin/CakePHP-Enum-Beh
./utils/zmeditconfigdata.sh ZM_OPT_FAST_DELETE no ./utils/zmeditconfigdata.sh ZM_OPT_FAST_DELETE no
%build %build
# Disable LTO due to top level asm
# See https://fedoraproject.org/wiki/LTOByDefault
%define _lto_cflags %{nil}
%cmake3 \ %cmake3 \
-DZM_WEB_USER="%{zmuid_final}" \ -DZM_WEB_USER="%{zmuid_final}" \
-DZM_WEB_GROUP="%{zmgid_final}" \ -DZM_WEB_GROUP="%{zmgid_final}" \
-DZM_TARGET_DISTRO="%{zmtargetdistro}" \ -DZM_TARGET_DISTRO="%{zmtargetdistro}" \
. .
%make_build %cmake3_build
%install %install
%make_install %cmake3_install
desktop-file-install \ desktop-file-install \
--dir %{buildroot}%{_datadir}/applications \ --dir %{buildroot}%{_datadir}/applications \

View File

@ -3,7 +3,7 @@ Section: net
Priority: optional Priority: optional
Maintainer: Isaac Connor <isaac@zoneminder.com> Maintainer: Isaac Connor <isaac@zoneminder.com>
Uploaders: Isaac Connor <isaac@zoneminder.com> Uploaders: Isaac Connor <isaac@zoneminder.com>
Build-Depends: debhelper, dh-systemd, python3-sphinx, dh-linktree, dh-systemd, dh-apache2 Build-Depends: debhelper, dh-systemd, sphinx-doc, dh-linktree, dh-systemd, dh-apache2
,cmake ,cmake
,libx264-dev, libmp4v2-dev ,libx264-dev, libmp4v2-dev
,libavdevice-dev ,libavdevice-dev

View File

@ -30,10 +30,10 @@ configure_file(zm.in "${CMAKE_CURRENT_BINARY_DIR}/zm" @ONLY)
#configure_file(zmeventdump.in zmeventdump @ONLY) #configure_file(zmeventdump.in zmeventdump @ONLY)
# Generate man files for the perl scripts destined for the bin folder # 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}) FOREACH(PERLSCRIPT ${perlscripts})
get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME) get_filename_component(PERLSCRIPTNAME ${PERLSCRIPT} NAME)
POD2MAN(${PERLSCRIPT} zoneminder-${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX}) POD2MAN(${PERLSCRIPT} ${PERLSCRIPTNAME} 8 ${ZM_MANPAGE_DEST_PREFIX})
ENDFOREACH(PERLSCRIPT ${perlscripts}) ENDFOREACH(PERLSCRIPT ${perlscripts})
# Install the perl scripts # Install the perl scripts

View File

@ -1513,6 +1513,26 @@ our @options = (
type => $types{boolean}, type => $types{boolean},
category => 'logging', category => 'logging',
}, },
{
name => 'ZM_WEB_NAVBAR_TYPE',
default => 'normal',
description => 'Style of the web console navigation bar',
help => q`
Choose between different navigation bar styles for the web
console. The "normal" style has a menu across the top, which
collapses to a pull down menu on small screens. The "collapsed"
style is collapsed all the time. Instead of a menu across the
top, menu items are accessed from the drop down menu on the
right.
`,
type => {
db_type => 'string',
hint => 'normal|collapsed',
pattern => qr|^([nc])|i,
format => q( ($1 =~ /^n/) ? 'normal' : 'collapsed' )
},
category => 'web',
},
{ {
name => 'ZM_WEB_TITLE', name => 'ZM_WEB_TITLE',
default => 'ZoneMinder', default => 'ZoneMinder',
@ -1558,6 +1578,20 @@ our @options = (
type => $types{string}, type => $types{string},
category => 'web', category => 'web',
}, },
{
name => 'ZM_HOME_ABOUT',
default => 'yes',
description => 'Whether to enable the ZoneMinder About menu.',
help => q`
When enabled, the ZoneMinder logo in the top left corner of the
navigation bar becomes a menu with links to: the ZoneMinder
website, ZoneMinder Documentation, and the ZoneMinder forum.
End users wishing to rebrand their system may want to disable this
as the menu items are currently hard coded.
`,
type => $types{boolean},
category => 'web',
},
{ {
name => 'ZM_WEB_CONSOLE_BANNER', name => 'ZM_WEB_CONSOLE_BANNER',
default => '', default => '',

View File

@ -113,7 +113,7 @@ sub open {
Debug('No headers line'); Debug('No headers line');
} # end if headers } # end if headers
} else { } else {
Warning('Failed to open '.$uri->canonical().$url.' status: '.$res->status_line()); Debug('Failed to open '.$uri->canonical().$url.' status: '.$res->status_line());
} # end if $res->status_line() eq '401 Unauthorized' } # end if $res->status_line() eq '401 Unauthorized'
} # end sub open } # end sub open

View File

@ -27,7 +27,7 @@ target_link_libraries(zms zm ${ZM_EXTRA_LIBS} ${ZM_BIN_LIBS} ${CMAKE_DL_LIBS} bc
# Generate man files for the binaries destined for the bin folder # Generate man files for the binaries destined for the bin folder
FOREACH(CBINARY zma zmc zmu) FOREACH(CBINARY zma zmc zmu)
POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp zoneminder-${CBINARY} 8 ${ZM_MANPAGE_DEST_PREFIX}) POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp ${CBINARY} 8 ${ZM_MANPAGE_DEST_PREFIX})
ENDFOREACH(CBINARY zma zmc zmu) ENDFOREACH(CBINARY zma zmc zmu)
install(TARGETS zmc zma zmu RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) install(TARGETS zmc zma zmu RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)

View File

@ -213,9 +213,11 @@ Event::Event(
if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) { if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) {
#if ZM_HAVE_VIDEOWRITER_X264MP4 #if ZM_HAVE_VIDEOWRITER_X264MP4
videowriter = new X264MP4Writer(video_file.c_str(), videowriter = new X264MP4Writer(video_file.c_str(),
monitor->Width(), monitor->Height(), monitor->Width(),
monitor->Colours(), monitor->SubpixelOrder(), monitor->Height(),
monitor->GetOptEncoderParams()); monitor->Colours(),
monitor->SubpixelOrder(),
monitor->GetOptEncoderParamsVec());
#else #else
Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)"); Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)");
#endif #endif
@ -279,7 +281,7 @@ Event::~Event() {
// Should not be static because we might be multi-threaded // Should not be static because we might be multi-threaded
char sql[ZM_SQL_LGE_BUFSIZ]; char sql[ZM_SQL_LGE_BUFSIZ];
snprintf(sql, sizeof(sql), snprintf(sql, sizeof(sql),
"UPDATE Events SET Name='%s %" PRIu64 "', EndTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64, "UPDATE Events SET Name='%s%" PRIu64 "', EndTime = from_unixtime(%ld), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d WHERE Id = %" PRIu64,
monitor->EventPrefix(), id, end_time.tv_sec, monitor->EventPrefix(), id, end_time.tv_sec,
delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec,
frames, alarm_frames, frames, alarm_frames,

View File

@ -1189,7 +1189,7 @@ int FfmpegCamera::transfer_to_image(
for ( int i = 0; i < output_frame->height; i++ ) { for ( int i = 0; i < output_frame->height; i++ ) {
memcpy(image_buffer_ptr, buffer, row_size); memcpy(image_buffer_ptr, buffer, row_size);
image_buffer_ptr += row_size; image_buffer_ptr += row_size;
buffer += row_size; buffer += output_frame->linesize[0];
} }
} }
return 0; return 0;

View File

@ -383,6 +383,7 @@ Monitor::Monitor(
strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-1); strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-1);
strncpy(label_format, p_label_format, sizeof(label_format)-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 // Change \n to actual line feeds
char *token_ptr = label_format; char *token_ptr = label_format;
@ -632,7 +633,7 @@ bool Monitor::connect() {
image_buffer = new Snapshot[image_buffer_count]; image_buffer = new Snapshot[image_buffer_count];
for ( int i = 0; i < image_buffer_count; i++ ) { for ( int i = 0; i < image_buffer_count; i++ ) {
image_buffer[i].timestamp = &(shared_timestamps[i]); image_buffer[i].timestamp = &(shared_timestamps[i]);
image_buffer[i].image = new Image(width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) ); image_buffer[i].image = new Image(width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]));
image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */
} }
if ( (deinterlacing & 0xff) == 4 ) { if ( (deinterlacing & 0xff) == 4 ) {
@ -1633,7 +1634,7 @@ bool Monitor::Analyse() {
} // end if pre_event_images } // end if pre_event_images
if ( ( alarm_frame_count > 1 ) && Event::PreAlarmCount() ) { if ( ( alarm_frame_count > 1 ) && Event::PreAlarmCount() ) {
Debug(1, "alarm frame count so SavePreAlarmFrames"); Debug(1, "alarm frame count so SavePreAlarmFrames");
event->SavePreAlarmFrames(); event->SavePreAlarmFrames();
} }
} // end if event } // end if event

View File

@ -473,7 +473,8 @@ public:
int GetOptSaveJPEGs() const { return savejpegs; } int GetOptSaveJPEGs() const { return savejpegs; }
VideoWriter GetOptVideoWriter() const { return videowriter; } 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; } 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; } 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; } struct timeval GetVideoWriterStartTime() const { return video_store_data->recording; }

View File

@ -40,16 +40,7 @@ VideoStream::MimeData VideoStream::mime_data[] = {
}; };
void VideoStream::Initialise( ) { void VideoStream::Initialise( ) {
if ( logDebugging() ) { FFMPEGInit();
av_log_set_level( AV_LOG_DEBUG );
} else {
av_log_set_level( AV_LOG_QUIET );
}
av_register_all( );
#if LIBAVFORMAT_VERSION_CHECK(53, 13, 0, 19, 0)
avformat_network_init();
#endif
initialised = true; initialised = true;
} }
@ -57,23 +48,23 @@ void VideoStream::SetupFormat( ) {
/* allocate the output media context */ /* allocate the output media context */
ofc = NULL; ofc = NULL;
#if (LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 2, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) #if (LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 2, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
avformat_alloc_output_context2( &ofc, NULL, format, filename ); avformat_alloc_output_context2(&ofc, NULL, format, filename);
#else #else
AVFormatContext *s= avformat_alloc_context(); AVFormatContext *s = avformat_alloc_context();
if(!s) { if ( !s ) {
Fatal( "avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc) ); Fatal("avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc));
return; return;
} }
AVOutputFormat *oformat; AVOutputFormat *oformat;
if (format) { if ( format ) {
#if LIBAVFORMAT_VERSION_CHECK(52, 45, 0, 45, 0) #if LIBAVFORMAT_VERSION_CHECK(52, 45, 0, 45, 0)
oformat = av_guess_format(format, NULL, NULL); oformat = av_guess_format(format, NULL, NULL);
#else #else
oformat = guess_format(format, NULL, NULL); oformat = guess_format(format, NULL, NULL);
#endif #endif
if (!oformat) { if ( !oformat ) {
Fatal( "Requested output format '%s' is not a suitable output format", format ); Fatal("Requested output format '%s' is not a suitable output format", format);
} }
} else { } else {
#if LIBAVFORMAT_VERSION_CHECK(52, 45, 0, 45, 0) #if LIBAVFORMAT_VERSION_CHECK(52, 45, 0, 45, 0)
@ -81,47 +72,47 @@ void VideoStream::SetupFormat( ) {
#else #else
oformat = guess_format(NULL, filename, NULL); oformat = guess_format(NULL, filename, NULL);
#endif #endif
if (!oformat) { if ( !oformat ) {
Fatal( "Unable to find a suitable output format for '%s'", format ); Fatal("Unable to find a suitable output format for '%s'", format);
} }
} }
s->oformat = oformat; s->oformat = oformat;
if (s->oformat->priv_data_size > 0) { if ( s->oformat->priv_data_size > 0 ) {
s->priv_data = av_mallocz(s->oformat->priv_data_size); s->priv_data = av_mallocz(s->oformat->priv_data_size);
if ( !(s->priv_data) ) { if ( !(s->priv_data) ) {
Fatal( "Could not allocate private data for output format." ); Fatal("Could not allocate private data for output format.");
} }
#if LIBAVFORMAT_VERSION_CHECK(52, 92, 0, 92, 0) #if LIBAVFORMAT_VERSION_CHECK(52, 92, 0, 92, 0)
if (s->oformat->priv_class) { if ( s->oformat->priv_class ) {
*(const AVClass**)s->priv_data = s->oformat->priv_class; *(const AVClass**)s->priv_data = s->oformat->priv_class;
av_opt_set_defaults(s->priv_data); av_opt_set_defaults(s->priv_data);
} }
#endif #endif
} else { } else {
Debug(1,"No allocating priv_data"); Debug(1, "No allocating priv_data");
s->priv_data = NULL; s->priv_data = NULL;
} }
if ( filename ) { if ( filename ) {
snprintf( s->filename, sizeof(s->filename), "%s", filename ); snprintf(s->filename, sizeof(s->filename), "%s", filename);
} }
ofc = s; ofc = s;
#endif #endif
if ( !ofc ) { if ( !ofc ) {
Fatal( "avformat_alloc_..._context failed: %d", ofc ); Fatal("avformat_alloc_..._context failed: %d", ofc);
} }
of = ofc->oformat; of = ofc->oformat;
Debug( 1, "Using output format: %s (%s)", of->name, of->long_name ); Debug(1, "Using output format: %s (%s)", of->name, of->long_name);
} }
void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ) { void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ) {
/* ffmpeg format matching */ /* ffmpeg format matching */
switch(colours) { switch ( colours ) {
case ZM_COLOUR_RGB24: case ZM_COLOUR_RGB24:
if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { if ( subpixelorder == ZM_SUBPIX_ORDER_BGR ) {
/* BGR subpixel order */ /* BGR subpixel order */
pf = AV_PIX_FMT_BGR24; pf = AV_PIX_FMT_BGR24;
} else { } else {
@ -130,13 +121,13 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
} }
break; break;
case ZM_COLOUR_RGB32: case ZM_COLOUR_RGB32:
if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
/* ARGB subpixel order */ /* ARGB subpixel order */
pf = AV_PIX_FMT_ARGB; pf = AV_PIX_FMT_ARGB;
} else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { } else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
/* ABGR subpixel order */ /* ABGR subpixel order */
pf = AV_PIX_FMT_ABGR; pf = AV_PIX_FMT_ABGR;
} else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { } else if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
/* BGRA subpixel order */ /* BGRA subpixel order */
pf = AV_PIX_FMT_BGRA; pf = AV_PIX_FMT_BGRA;
} else { } else {
@ -152,7 +143,7 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
break; break;
} }
if ( strcmp( "rtp", of->name ) == 0 ) { if ( strcmp("rtp", of->name) == 0 ) {
// RTP must have a packet_size. // RTP must have a packet_size.
// Not sure what this value should be really... // Not sure what this value should be really...
ofc->packet_size = width*height; ofc->packet_size = width*height;
@ -169,12 +160,12 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
AVCodec *a = avcodec_find_encoder_by_name(codec_name); AVCodec *a = avcodec_find_encoder_by_name(codec_name);
if ( a ) { if ( a ) {
codec_id = a->id; codec_id = a->id;
Debug( 1, "Using codec \"%s\"", codec_name ); Debug(1, "Using codec \"%s\"", codec_name);
} else { } else {
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
Debug( 1, "Could not find codec \"%s\". Using default \"%s\"", codec_name, avcodec_get_name( codec_id ) ); Debug(1, "Could not find codec \"%s\". Using default \"%s\"", codec_name, avcodec_get_name(codec_id));
#else #else
Debug( 1, "Could not find codec \"%s\". Using default \"%d\"", codec_name, codec_id ); Debug(1, "Could not find codec \"%s\". Using default \"%d\"", codec_name, codec_id);
#endif #endif
} }
} }
@ -183,19 +174,19 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei
and initialize the codecs */ and initialize the codecs */
ost = NULL; ost = NULL;
if ( codec_id != AV_CODEC_ID_NONE ) { if ( codec_id != AV_CODEC_ID_NONE ) {
codec = avcodec_find_encoder( codec_id ); codec = avcodec_find_encoder(codec_id);
if ( !codec ) { if ( !codec ) {
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
Fatal( "Could not find encoder for '%s'", avcodec_get_name( codec_id ) ); Fatal("Could not find encoder for '%s'", avcodec_get_name(codec_id));
#else #else
Fatal( "Could not find encoder for '%d'", codec_id ); Fatal("Could not find encoder for '%d'", codec_id);
#endif #endif
} }
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
Debug( 1, "Found encoder for '%s'", avcodec_get_name( codec_id ) ); Debug(1, "Found encoder for '%s'", avcodec_get_name(codec_id));
#else #else
Debug( 1, "Found encoder for '%d'", codec_id ); Debug(1, "Found encoder for '%d'", codec_id);
#endif #endif
#if LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0) #if LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0)

View File

@ -624,8 +624,8 @@ int RemoteCameraHttp::GetResponse() {
static char *content_type_header; static char *content_type_header;
static char *boundary_header; static char *boundary_header;
static char *authenticate_header; static char *authenticate_header;
static char subcontent_length_header[32]; static char subcontent_length_header[33];
static char subcontent_type_header[64]; static char subcontent_type_header[65];
static char http_version[16]; static char http_version[16];
static char status_code[16]; static char status_code[16];
@ -896,25 +896,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; //subheaders[n_subheaders++] = subheader_ptr;
n_subheaders++; 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; boundary_header = subheader_ptr;
Debug( 4, "Got boundary subheader '%s'", 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) ) { } else if (
strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) ); !subcontent_length_header[0]
*(subcontent_length_header+strcspn( subcontent_length_header, "\r\n" )) = '\0'; &&
Debug( 4, "Got content length subheader '%s'", subcontent_length_header ); (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) ) { } 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) ); strncpy(
*(subcontent_type_header+strcspn( subcontent_type_header, "\r\n" )) = '\0'; subcontent_type_header,
Debug( 4, "Got content type subheader '%s'", 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 { } else {
Debug( 6, "Got ignored subheader '%s' found", subheader_ptr ); Debug(6, "Got ignored subheader '%s' found", subheader_ptr);
} }
subheader_ptr = crlf; subheader_ptr = crlf;
subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); subheader_len -= buffer.consume( subheader_ptr-(char *)buffer );
@ -1057,6 +1069,18 @@ int RemoteCameraHttp::GetResponse() {
return( 0 ); return( 0 );
} }
int RemoteCameraHttp::PrimeCapture() {
if ( sd < 0 ) {
Connect();
if ( sd < 0 ) {
return -1;
}
mode = SINGLE_IMAGE;
buffer.clear();
}
return 0;
}
int RemoteCameraHttp::PreCapture() { int RemoteCameraHttp::PreCapture() {
if ( sd < 0 ) { if ( sd < 0 ) {
Connect(); Connect();

View File

@ -55,6 +55,7 @@ public:
int ReadData( Buffer &buffer, unsigned int bytes_expected=0 ); int ReadData( Buffer &buffer, unsigned int bytes_expected=0 );
int GetData(); int GetData();
int GetResponse(); int GetResponse();
int PrimeCapture();
int PreCapture(); int PreCapture();
int Capture( Image &image ); int Capture( Image &image );
int PostCapture(); int PostCapture();

View File

@ -37,11 +37,12 @@ VideoStore::VideoStore(
const char *format_in, const char *format_in,
AVStream *p_video_in_stream, AVStream *p_video_in_stream,
AVStream *p_audio_in_stream, AVStream *p_audio_in_stream,
Monitor *monitor Monitor *p_monitor
) { ) {
video_in_stream = p_video_in_stream; video_in_stream = p_video_in_stream;
audio_in_stream = p_audio_in_stream; audio_in_stream = p_audio_in_stream;
monitor = p_monitor;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
//video_in_ctx = avcodec_alloc_context3(NULL); //video_in_ctx = avcodec_alloc_context3(NULL);
@ -213,11 +214,18 @@ VideoStore::VideoStore(
} }
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0) #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 /* 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 * * think what I was trying to achieve here was to have zm_dump_codecpar output nice info
* */ * */
#if 0
AVDictionary *opts = 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 ) { if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
Warning("Can't open video codec (%s) %s", Warning("Can't open video codec (%s) %s",
video_out_codec->name, video_out_codec->name,
@ -404,21 +412,39 @@ bool VideoStore::open() {
} }
zm_dump_stream_format(oc, 0, 0, 1); 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; 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 std::string option_string = monitor->GetOptEncoderParams();
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); ret = av_dict_parse_string(&opts, option_string.c_str(), "=", ",\n", 0);
// av_dict_set(&opts, "movflags", if ( ret < 0 ) {
// "frag_keyframe+empty_moov+default_base_moof", 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 ) {
// if ((ret = avformat_write_header(oc, &opts)) < 0) { Warning("Unable to set movflags trying with defaults.");
Warning("Unable to set movflags to frag_custom+dash+delay_moov");
/* Write the stream header, if any. */
ret = avformat_write_header(oc, NULL); ret = avformat_write_header(oc, NULL);
} else if (av_dict_count(opts) != 0) { } else if ( av_dict_count(opts) != 0 ) {
Warning("some options not set"); 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 ( opts ) av_dict_free(&opts);
if ( ret < 0 ) { if ( ret < 0 ) {

View File

@ -19,7 +19,6 @@ extern "C" {
class VideoStore { class VideoStore {
private: private:
AVOutputFormat *out_format; AVOutputFormat *out_format;
AVFormatContext *oc; AVFormatContext *oc;
@ -30,6 +29,7 @@ private:
AVStream *video_in_stream; AVStream *video_in_stream;
AVStream *audio_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 // Move this into the object so that we aren't constantly allocating/deallocating it on the stack
AVPacket opkt; AVPacket opkt;

View File

@ -227,12 +227,11 @@ IFS=',' ;for DISTRO in `echo "$DISTROS"`; do
# Generate Changlog # Generate Changlog
if [ "$DISTRO" == "focal" ] || [ "$DISTRO" == "buster" ]; then if [ "$DISTRO" == "focal" ] || [ "$DISTRO" == "buster" ]; then
cp -Rpd distros/ubuntu2004 debian cp -Rpd distros/ubuntu2004 debian
elif [ "$DISTRO" == "beowulf" ]
then
cp -Rpd distros/beowulf debian
else else
if [ "$DISTRO" == "wheezy" ]; then cp -Rpd distros/ubuntu1604 debian
cp -Rpd distros/debian debian
else
cp -Rpd distros/ubuntu1604 debian
fi;
fi; fi;
if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then if [ "$DEBEMAIL" != "" ] && [ "$DEBFULLNAME" != "" ]; then

View File

@ -1,5 +1,6 @@
<?php <?php
if ( $_REQUEST['entity'] == 'navBar' ) { if ( $_REQUEST['entity'] == 'navBar' ) {
global $bandwidth_options, $user;
$data = array(); $data = array();
if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) { if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') ) {
$auth_hash = generateAuthHash(ZM_AUTH_HASH_IPS); $auth_hash = generateAuthHash(ZM_AUTH_HASH_IPS);
@ -7,7 +8,14 @@ if ( $_REQUEST['entity'] == 'navBar' ) {
$data['auth'] = $auth_hash; $data['auth'] = $auth_hash;
} }
} }
$data['message'] = getNavBarHtml('reload'); // Each widget on the navbar has its own function
// Call the functions we want to dynamically update
$data['getBandwidthHTML'] = getBandwidthHTML($bandwidth_options, $user);
$data['getSysLoadHTML'] = getSysLoadHTML();
$data['getDbConHTML'] = getDbConHTML();
$data['getStorageHTML'] = getStorageHTML();
$data['getShmHTML'] = getShmHTML();
ajaxResponse($data); ajaxResponse($data);
return; return;
} }
@ -246,7 +254,7 @@ function collectData() {
if ( isset($elementData['sql']) ) if ( isset($elementData['sql']) )
$fieldSql[] = $elementData['sql'].' as '.$element; $fieldSql[] = $elementData['sql'].' as '.$element;
else else
$fieldSql[] = $element; $fieldSql[] = '`'.$element.'`';
if ( isset($elementData['table']) && isset($elementData['join']) ) { if ( isset($elementData['table']) && isset($elementData['join']) ) {
$joinSql[] = 'left join '.$elementData['table'].' on '.$elementData['join']; $joinSql[] = 'left join '.$elementData['table'].' on '.$elementData['join'];
} }
@ -286,7 +294,7 @@ function collectData() {
preg_match('/^`?(\w+)`?\s*(ASC|DESC)?( NULLS FIRST)?$/i', $sort_field, $matches); preg_match('/^`?(\w+)`?\s*(ASC|DESC)?( NULLS FIRST)?$/i', $sort_field, $matches);
if ( count($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]; $sql .= $matches[1];
} else { } else {
ZM\Error('Sort field '.$matches[1].' from ' .$sort_field.' not in SQL Fields: '.join(',', $sort_field)); ZM\Error('Sort field '.$matches[1].' from ' .$sort_field.' not in SQL Fields: '.join(',', $sort_field));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -262,13 +262,18 @@ class Event extends ZM_Object {
return $streamSrc; return $streamSrc;
} // end function getStreamSrc } // 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='' ) { function DiskSpace( $new='' ) {
if ( is_null($new) or ( $new != '' ) ) { if ( is_null($new) or ( $new != '' ) ) {
$this->{'DiskSpace'} = $new; $this->{'DiskSpace'} = $new;
} }
if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) { if ( (!property_exists($this, 'DiskSpace')) or (null === $this->{'DiskSpace'}) ) {
$this->{'DiskSpace'} = folder_size($this->Path()); $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'}; return $this->{'DiskSpace'};
} }

View File

@ -205,8 +205,8 @@ class Monitor extends ZM_Object {
if ( ZM_RAND_STREAM ) { if ( ZM_RAND_STREAM ) {
$args['rand'] = time(); $args['rand'] = time();
} }
foreach ( array('scale','height','width') as $int_arg ) { foreach ( array('scale') as $int_arg ) {
if ( isset($args[$int_arg]) and (!is_int($args[$int_arg]) or !$args[$int_arg] ) ) { if ( isset($args[$int_arg]) and (!is_numeric($args[$int_arg]) or !$args[$int_arg] ) ) {
unset($args[$int_arg]); unset($args[$int_arg]);
} }
} }

View File

@ -153,7 +153,7 @@ class ZM_Object {
public function to_json() { public function to_json() {
$json = array(); $json = array();
foreach ($this->defaults as $key => $value) { foreach ($this->defaults as $key => $value) {
if ( is_callable(array($this, $key)) ) { if ( is_callable(array($this, $key), false) ) {
$json[$key] = $this->$key(); $json[$key] = $this->$key();
} else if ( property_exists($this, $key) ) { } else if ( property_exists($this, $key) ) {
$json[$key] = $this->{$key}; $json[$key] = $this->{$key};
@ -166,17 +166,17 @@ class ZM_Object {
public function set($data) { public function set($data) {
foreach ( $data as $field => $value ) { foreach ( $data as $field => $value ) {
if ( is_callable(array($this, $field)) ) { if ( method_exists($this, $field) and is_callable(array($this, $field), false) ) {
$this->{$field}($value); $this->$field($value);
} else { } else {
if ( is_array($value) ) { if ( is_array($value) ) {
# perhaps should turn into a comma-separated string # perhaps should turn into a comma-separated string
$this->{$field} = implode(',', $value); $this->{$field} = implode(',', $value);
} else if ( is_string($value) ) { } else if ( is_string($value) ) {
if ( array_key_exists($field, $this->defaults) && is_array($this->defaults[$field]) && isset($this->defaults[$field]['filter_regexp']) ) { if ( array_key_exists($field, $this->defaults) && is_array($this->defaults[$field]) && isset($this->defaults[$field]['filter_regexp']) ) {
if ( is_array($this->defaults[$feild]['filter_regexp']) ) { if ( is_array($this->defaults[$field]['filter_regexp']) ) {
foreach ( $this->defaults[$field]['filter_regexp'] as $regexp ) { foreach ( $this->defaults[$field]['filter_regexp'] as $regexp ) {
$this->{$field} = preg_replace($regexp, '', $trim($value)); $this->{$field} = preg_replace($regexp, '', trim($value));
} }
} else { } else {
$this->{$field} = preg_replace($this->defaults[$field]['filter_regexp'], '', trim($value)); $this->{$field} = preg_replace($this->defaults[$field]['filter_regexp'], '', trim($value));

View File

@ -100,10 +100,14 @@ class Server extends ZM_Object {
$url = $this->Protocol().'://'; $url = $this->Protocol().'://';
$url .= $this->Hostname(); $url .= $this->Hostname();
if ( $port ) { if ( !$port ) {
$url .= ':'.$port; $port = $this->Port();
}
if ( $this->Protocol() == 'https' and $port == 443 ) {
} else if ( $this->Protocol() == 'http' and $port == 80 ) {
} else { } else {
$url .= ':'.$this->Port(); Logger::Debug("Adding port $port for " . $this->Protocol());
$url .= ':'.$port;
} }
return $url; return $url;
} }

View File

@ -26,7 +26,8 @@ class Storage extends ZM_Object {
return ZM_Object::_find_one(get_class(), $parameters, $options); return ZM_Object::_find_one(get_class(), $parameters, $options);
} }
public function Path() { public function Path($new=null) {
if ( $new ) $this->{'Path'} = $new;
if ( isset($this->{'Path'}) and ( $this->{'Path'} != '' ) ) { if ( isset($this->{'Path'}) and ( $this->{'Path'} != '' ) ) {
return $this->{'Path'}; return $this->{'Path'};
} else if ( ! isset($this->{'Id'}) ) { } else if ( ! isset($this->{'Id'}) ) {
@ -40,7 +41,9 @@ class Storage extends ZM_Object {
} }
return $this->{'Name'}; return $this->{'Name'};
} }
public function Name() { public function Name($new=null) {
if ( $new )
$this->{'Name'} = $new;
if ( isset($this->{'Name'}) and ( $this->{'Name'} != '' ) ) { if ( isset($this->{'Name'}) and ( $this->{'Name'} != '' ) ) {
return $this->{'Name'}; return $this->{'Name'};
} else if ( ! isset($this->{'Id'}) ) { } else if ( ! isset($this->{'Id'}) ) {

View File

@ -40,7 +40,7 @@ function CSPHeaders($view, $nonce) {
if ( ! $Servers ) if ( ! $Servers )
$Servers = ZM\Server::find(); $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) { switch ($view) {
case 'login': { case 'login': {
if (defined('ZM_OPT_USE_GOOG_RECAPTCHA') if (defined('ZM_OPT_USE_GOOG_RECAPTCHA')
@ -2232,8 +2232,8 @@ function generateConnKey() {
function detaintPath($path) { function detaintPath($path) {
// Remove any absolute paths, or relative ones that want to go up // Remove any absolute paths, or relative ones that want to go up
$path = preg_replace('/\.(?:\.+[\\/][\\/]*)+/', '', $path); $path = str_replace('../', '', $path);
$path = preg_replace('/^[\\/]+/', '', $path); $path = ltrim($path, '/');
return $path; return $path;
} }
@ -2242,7 +2242,7 @@ function cache_bust($file) {
# To defeat caching. Should probably use md5 hash # To defeat caching. Should probably use md5 hash
$parts = pathinfo($file); $parts = pathinfo($file);
global $css; global $css;
$dirname = preg_replace('/\//', '_', $parts['dirname']); $dirname = str_replace('/', '_', $parts['dirname']);
$cacheFile = $dirname.'_'.$parts['filename'].'-'.$css.'-'.filemtime($file).'.'.$parts['extension']; $cacheFile = $dirname.'_'.$parts['filename'].'-'.$css.'-'.filemtime($file).'.'.$parts['extension'];
if ( file_exists(ZM_DIR_CACHE.'/'.$cacheFile) or symlink(ZM_PATH_WEB.'/'.$file, ZM_DIR_CACHE.'/'.$cacheFile) ) { if ( file_exists(ZM_DIR_CACHE.'/'.$cacheFile) or symlink(ZM_PATH_WEB.'/'.$file, ZM_DIR_CACHE.'/'.$cacheFile) ) {
return 'cache/'.$cacheFile; return 'cache/'.$cacheFile;
@ -2256,7 +2256,7 @@ function getSkinFile($file) {
global $skinBase; global $skinBase;
$skinFile = false; $skinFile = false;
foreach ( $skinBase as $skin ) { foreach ( $skinBase as $skin ) {
$tempSkinFile = detaintPath('skins'.'/'.$skin.'/'.$file); $tempSkinFile = detaintPath('skins/'.$skin.'/'.$file);
if ( file_exists($tempSkinFile) ) if ( file_exists($tempSkinFile) )
$skinFile = $tempSkinFile; $skinFile = $tempSkinFile;
} }
@ -2267,7 +2267,7 @@ function getSkinIncludes($file, $includeBase=false, $asOverride=false) {
global $skinBase; global $skinBase;
$skinFile = false; $skinFile = false;
foreach ( $skinBase as $skin ) { foreach ( $skinBase as $skin ) {
$tempSkinFile = detaintPath('skins'.'/'.$skin.'/'.$file); $tempSkinFile = detaintPath('skins/'.$skin.'/'.$file);
if ( file_exists($tempSkinFile) ) if ( file_exists($tempSkinFile) )
$skinFile = $tempSkinFile; $skinFile = $tempSkinFile;
} }

View File

@ -1,35 +1,43 @@
<?php <?php
// ZM session start function support timestamp management // ZM session start function support timestamp management
function zm_session_start() { function zm_session_start() {
// Make sure use_strict_mode is enabled.
// use_strict_mode is mandatory for security reasons.
ini_set('session.use_strict_mode', 1);
$currentCookieParams = session_get_cookie_params(); if ( ini_get('session.name') != 'ZMSESSID' ) {
$currentCookieParams['lifetime'] = ZM_COOKIE_LIFETIME; // Make sure use_strict_mode is enabled.
// use_strict_mode is mandatory for security reasons.
ini_set('session.use_strict_mode', 1);
session_set_cookie_params( $currentCookieParams = session_get_cookie_params();
$currentCookieParams['lifetime'], $currentCookieParams['lifetime'] = ZM_COOKIE_LIFETIME;
$currentCookieParams['path'], $currentCookieParams['httponly'] = true;
$currentCookieParams['domain'], if ( version_compare(phpversion(), '7.3.0', '<') ) {
$currentCookieParams['secure'], session_set_cookie_params(
true $currentCookieParams['lifetime'],
); $currentCookieParams['path'],
$currentCookieParams['domain'],
ini_set('session.name', 'ZMSESSID'); $currentCookieParams['secure'],
ZM\Logger::Debug('Setting cookie parameters to lifetime('.$currentCookieParams['lifetime'].') path('.$currentCookieParams['path'].') domain ('.$currentCookieParams['domain'].') secure('.$currentCookieParams['secure'].') httpOnly(1) name:'.session_name()); $currentCookieParams['httponly']
);
} else {
# samesite was introduced in 7.3.0
$currentCookieParams['samesite'] = 'Strict';
session_set_cookie_params($currentCookieParams);
}
ini_set('session.name', 'ZMSESSID');
ZM\Logger::Debug('Setting cookie parameters to '.print_r($currentCookieParams, true));
}
session_start(); session_start();
$_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking $_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking
$now = time(); $now = time();
// Do not allow to use expired session ID // Do not allow to use expired session ID
if ( !empty($_SESSION['last_time']) && ($_SESSION['last_time'] < ($now - 180)) ) { if ( !empty($_SESSION['last_time']) && ($_SESSION['last_time'] < ($now - 180)) ) {
ZM\Info('Destroying session due to timeout. '); ZM\Info('Destroying session due to timeout.');
session_destroy(); session_destroy();
session_start(); session_start();
} else if ( !empty($_SESSION['generated_at']) ) { } else if ( !empty($_SESSION['generated_at']) ) {
if ( $_SESSION['generated_at']<($now-(ZM_COOKIE_LIFETIME/2)) ) { if ( $_SESSION['generated_at']<($now-(ZM_COOKIE_LIFETIME/2)) ) {
ZM\Logger::Debug("Regenerating session because generated_at " . $_SESSION['generated_at'] . ' < ' . $now . '-'.ZM_COOKIE_LIFETIME.'/2 = '.($now-ZM_COOKIE_LIFETIME/2)); ZM\Logger::Debug('Regenerating session because generated_at ' . $_SESSION['generated_at'] . ' < ' . $now . '-'.ZM_COOKIE_LIFETIME.'/2 = '.($now-ZM_COOKIE_LIFETIME/2));
zm_session_regenerate_id(); zm_session_regenerate_id();
} }
} }

View File

@ -993,6 +993,18 @@ $OLANG = array(
"loglevel=debug" Set verbosity of FFmpeg (quiet, panic, fatal, error, warning, info, verbose, debug) "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( 'OPTIONS_DECODERHWACCELNAME' => array(
'Help' => ' '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.' 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.'

View File

@ -709,3 +709,9 @@ li.search-choice {
.form-check-inline { .form-check-inline {
display: inline-block; display: inline-block;
} }
#dropdown_storage+div,
#dropdown_reminder+div,
#dropdown_bandwidth+div {
background-color:#485460;
}

View File

@ -11,6 +11,7 @@
textarea, textarea,
input[name="newMonitor[Name]"], input[name="newMonitor[Name]"],
input[name="newMonitor[LabelFormat]"],
input[name="newMonitor[ControlDevice]"], input[name="newMonitor[ControlDevice]"],
input[name="newMonitor[ControlAddress]"] { input[name="newMonitor[ControlAddress]"] {
width: 100%; width: 100%;

View File

@ -26,3 +26,7 @@ input[name="newConfig[ZM_OPT_GOOG_RECAPTCHA_SITEKEY]"],
input[name="newConfig[ZM_OPT_GOOG_RECAPTCHA_SECRETKEY]"] { input[name="newConfig[ZM_OPT_GOOG_RECAPTCHA_SECRETKEY]"] {
width: 100%; width: 100%;
} }
#options label {
font-weight: bold;
}

View File

@ -1,3 +1,12 @@
<?php
global $chart;
global $max_aspect_ratio;
global $monitors;
global $mode;
global $monEventSlots;
?>
.chartSize { .chartSize {
height: <?php echo $chart['height'] ?>px; height: <?php echo $chart['height'] ?>px;
} }
@ -19,6 +28,7 @@
.imageHeight { .imageHeight {
<?php <?php
switch ( $max_aspect_ratio ) { switch ( $max_aspect_ratio ) {
case null:
case 1: case 1:
echo 'padding-top: 100%;'; break; echo 'padding-top: 100%;'; break;
case 1.33: // 4:3 case 1.33: // 4:3

View File

@ -4,11 +4,13 @@
} }
#settingsPanel, #settingsPanel,
#zonePoints { #zonePoints {
width: 600px; max-width: 600px;
width: 50%;
} }
#zoneSettings { #zoneSettings {
border-collapse: collapse; border-collapse: collapse;
width: 100%;
} }
#zoneSettings th, #zoneSettings th,
@ -132,5 +134,22 @@ width: 100%;
input[name="newAlarmRgbR"], input[name="newAlarmRgbR"],
input[name="newAlarmRgbG"], input[name="newAlarmRgbG"],
input[name="newAlarmRgbB"] { input[name="newAlarmRgbB"] {
width: 30%; width: 25%;
}
input[name="newZone[MinPixelThreshold]"],
input[name="newZone[MaxPixelThreshold]"],
input[name="newZone[FilterX]"],
input[name="newZone[FilterY]"],
input[name="newZone[MinFilterPixels]"],
input[name="newZone[MaxFilterPixels]"],
input[name="newZone[MinBlobPixels]"],
input[name="newZone[MaxBlobPixels]"],
input[name="newZone[MinBlobs]"],
input[name="newZone[MaxBlobs]"],
input[name="newZone[MinAlarmPixels]"],
input[name="newZone[MaxAlarmPixels]"] {
width: 90px;
}
input.ZonePoint {
width: 75px;
} }

View File

@ -18,11 +18,13 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
function xhtmlHeaders($file, $title) { function xhtmlHeaders($file, $title) {
ob_start();
global $css; global $css;
global $skin; global $skin;
global $view; global $view;
global $cspNonce;
# This idea is that we always include the classic css files, # This idea is that we always include the classic css files,
# and then any different skin only needs to contain things that are different. # and then any different skin only needs to contain things that are different.
@ -40,8 +42,6 @@ function xhtmlHeaders($file, $title) {
$viewJsFile = getSkinFile('views/js/'.$basename.'.js'); $viewJsFile = getSkinFile('views/js/'.$basename.'.js');
$viewJsPhpFile = getSkinFile('views/js/'.$basename.'.js.php'); $viewJsPhpFile = getSkinFile('views/js/'.$basename.'.js.php');
extract($GLOBALS, EXTR_OVERWRITE);
function output_link_if_exists($files) { function output_link_if_exists($files) {
global $skin; global $skin;
$html = array(); $html = array();
@ -51,7 +51,7 @@ function xhtmlHeaders($file, $title) {
} }
} }
$html[] = ''; // So we ge a trailing \n $html[] = ''; // So we ge a trailing \n
return implode("\n", $html); return implode(PHP_EOL, $html);
} }
function output_cache_busted_stylesheet_links($files) { function output_cache_busted_stylesheet_links($files) {
@ -59,7 +59,8 @@ function xhtmlHeaders($file, $title) {
foreach ( $files as $file ) { foreach ( $files as $file ) {
$html[] = '<link rel="stylesheet" href="'.cache_bust($file).'" type="text/css"/>'; $html[] = '<link rel="stylesheet" href="'.cache_bust($file).'" type="text/css"/>';
} }
return implode("\n", $html); $html[] = ''; // So we ge a trailing \n
return implode(PHP_EOL, $html);
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@ -68,7 +69,7 @@ function xhtmlHeaders($file, $title) {
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo validHtmlStr(ZM_WEB_TITLE_PREFIX); ?> - <?php echo validHtmlStr($title) ?></title> <title><?php echo validHtmlStr(ZM_WEB_TITLE_PREFIX) . ' - ' . validHtmlStr($title) ?></title>
<?php <?php
if ( file_exists("skins/$skin/css/$css/graphics/favicon.ico") ) { if ( file_exists("skins/$skin/css/$css/graphics/favicon.ico") ) {
echo " echo "
@ -87,25 +88,22 @@ echo output_cache_busted_stylesheet_links(array(
'css/bootstrap.min.css', 'css/bootstrap.min.css',
)); ));
echo output_link_if_exists( array( echo output_link_if_exists(array(
'css/base/skin.css', 'css/base/skin.css',
'css/base/views/'.$basename.'.css', 'css/base/views/'.$basename.'.css',
'js/dateTimePicker/jquery-ui-timepicker-addon.css', 'js/dateTimePicker/jquery-ui-timepicker-addon.css',
'js/jquery-ui-1.12.1/jquery-ui.structure.min.css', 'js/jquery-ui-1.12.1/jquery-ui.structure.min.css',
) ));
);
if ( $css != 'base' ) if ( $css != 'base' )
echo output_link_if_exists( array( echo output_link_if_exists(array(
'css/'.$css.'/skin.css', 'css/'.$css.'/skin.css',
'css/'.$css.'/views/'.$basename.'.css', 'css/'.$css.'/views/'.$basename.'.css',
'css/'.$css.'/jquery-ui-theme.css', 'css/'.$css.'/jquery-ui-theme.css',
) ));
);
?> ?>
<link rel="stylesheet" href="skins/classic/js/jquery-ui-1.12.1/jquery-ui.theme.min.css" type="text/css"/>
<link rel="stylesheet" href="skins/classic/js/jquery-ui-1.12.1/jquery-ui.theme.min.css" type="text/css"/> <?php #Chosen can't be cache-busted because it loads sprites by relative path ?>
<!--Chosen can't be cache-busted because it loads sprites by relative path--> <link rel="stylesheet" href="skins/classic/js/chosen/chosen.min.css" type="text/css"/>
<link rel="stylesheet" href="skins/classic/js/chosen/chosen.min.css" type="text/css"/>
<?php <?php
if ( $basename == 'watch' ) { if ( $basename == 'watch' ) {
echo output_link_if_exists(array('/css/base/views/control.css')); echo output_link_if_exists(array('/css/base/views/control.css'));
@ -123,10 +121,8 @@ if ( $css != 'base' )
} }
?> ?>
</style> </style>
<?php
?>
<?php if ( $basename != 'login' ) { ?> <?php if ( $basename != 'login' and $basename != 'postlogin' ) { ?>
<script src="tools/mootools/mootools-core.js"></script> <script src="tools/mootools/mootools-core.js"></script>
<script src="tools/mootools/mootools-more.js"></script> <script src="tools/mootools/mootools-more.js"></script>
<script src="js/mootools.ext.js"></script> <script src="js/mootools.ext.js"></script>
@ -138,36 +134,7 @@ if ( $css != 'base' )
<script src="skins/<?php echo $skin; ?>/js/dateTimePicker/jquery-ui-timepicker-addon.js"></script> <script src="skins/<?php echo $skin; ?>/js/dateTimePicker/jquery-ui-timepicker-addon.js"></script>
<script src="<?php echo cache_bust('js/Server.js'); ?>"></script> <script src="<?php echo cache_bust('js/Server.js'); ?>"></script>
<script nonce="<?php echo $cspNonce; ?>"> <script nonce="<?php echo $cspNonce; ?>">var $j = jQuery.noConflict();</script>
jQuery(document).ready(function() {
jQuery("#flip").click(function() {
jQuery("#panel").slideToggle("slow");
var flip = jQuery("#flip");
if ( flip.html() == 'keyboard_arrow_up' ) {
flip.html('keyboard_arrow_down');
Cookie.write('zmHeaderFlip', 'down', {duration: 10*365} );
} else {
flip.html('keyboard_arrow_up');
Cookie.write('zmHeaderFlip', 'up', {duration: 10*365} );
}
});
jQuery("#fbflip").click(function() {
jQuery("#fbpanel").slideToggle("slow");
var fbflip = jQuery("#fbflip");
if ( fbflip.html() == 'keyboard_arrow_up' ) {
fbflip.html('keyboard_arrow_down');
Cookie.write('zmFilterBarFlip', 'down', {duration: 10*365} );
} else {
fbflip.html('keyboard_arrow_up');
Cookie.write('zmFilterBarFlip', 'up', {duration: 10*365} );
jQuery('.chosen').chosen("destroy");
jQuery('.chosen').chosen();
}
});
});
var $j = jQuery.noConflict();
// $j is now an alias to the jQuery function; creating the new alias is optional.
</script>
<script src="<?php echo cache_bust('skins/'.$skin.'/views/js/state.js') ?>"></script> <script src="<?php echo cache_bust('skins/'.$skin.'/views/js/state.js') ?>"></script>
<?php <?php
if ( $view == 'event' ) { if ( $view == 'event' ) {
@ -206,7 +173,8 @@ if ( $css != 'base' )
} else { } else {
?> ?>
<script src="<?php echo cache_bust('skins/classic/js/base.js') ?>"></script> <script src="<?php echo cache_bust('skins/classic/js/base.js') ?>"></script>
<?php } <?php
}
$skinJsFile = getSkinFile('js/skin.js'); $skinJsFile = getSkinFile('js/skin.js');
?> ?>
<script src="<?php echo cache_bust($skinJsFile) ?>"></script> <script src="<?php echo cache_bust($skinJsFile) ?>"></script>
@ -226,6 +194,7 @@ if ( $css != 'base' )
?> ?>
</head> </head>
<?php <?php
echo ob_get_clean();
} // end function xhtmlHeaders( $file, $title ) } // end function xhtmlHeaders( $file, $title )
// Outputs an opening body tag, and any additional content that should go at the very top, like warnings and error messages. // Outputs an opening body tag, and any additional content that should go at the very top, like warnings and error messages.
@ -245,7 +214,7 @@ function getBodyTopHTML() {
} }
} // end function getBodyTopHTML } // end function getBodyTopHTML
function getNavBarHTML($reload = null) { function getNavBarHTML() {
# Provide a facility to turn off the headers if you put navbar=0 into the url # Provide a facility to turn off the headers if you put navbar=0 into the url
if ( isset($_REQUEST['navbar']) and $_REQUEST['navbar'] == '0' ) if ( isset($_REQUEST['navbar']) and $_REQUEST['navbar'] == '0' )
return ''; return '';
@ -258,26 +227,34 @@ function getNavBarHTML($reload = null) {
global $sortQuery; global $sortQuery;
global $limitQuery; global $limitQuery;
if (!$sortQuery) { if ( !$sortQuery ) {
parseSort(); parseSort();
} }
if ( (!$filterQuery) and isset($_REQUEST['filter']) ) { if ( (!$filterQuery) and isset($_REQUEST['filter']) ) {
parseFilter($_REQUEST['filter']); parseFilter($_REQUEST['filter']);
$filterQuery = $_REQUEST['filter']['query']; $filterQuery = $_REQUEST['filter']['query'];
} }
if ( $reload === null ) {
ob_start(); ob_start();
if ( $running == null )
$running = daemonCheck(); if ( ZM_WEB_NAVBAR_TYPE == "normal" ) {
if ( $running ) { echo getNormalNavBarHTML($running, $user, $bandwidth_options, $view, $filterQuery, $sortQuery, $limitQuery);
$state = dbFetchOne('SELECT Name FROM States WHERE isActive=1', 'Name'); } else {
if ( $state == 'default' ) echo getCollapsedNavBarHTML($running, $user, $bandwidth_options, $view, $filterQuery, $sortQuery, $limitQuery);
$state = ''; }
}
$status = $running ? ($state ? $state : translate('Running')) : translate('Stopped'); return ob_get_clean();
}
//
// The legacy navigation bar that collapses into a pulldown menu on small screens.
//
function getNormalNavBarHTML($running, $user, $bandwidth_options, $view, $filterQuery, $sortQuery, $limitQuery) {
$status = runtimeStatus($running);
?> ?>
<div class="fixed-top container-fluid p-0 p-0"> <div class="fixed-top container-fluid p-0">
<nav class="navbar navbar-expand-md navbar-dark bg-dark justify-content-center flex-row"> <nav class="navbar navbar-expand-md navbar-dark bg-dark justify-content-center flex-row">
<div class="navbar-brand justify-content-start align-self-start"> <div class="navbar-brand justify-content-start align-self-start">
@ -297,17 +274,17 @@ function getNavBarHTML($reload = null) {
// *** Build the navigation bar menu items *** // *** Build the navigation bar menu items ***
if ( $user and $user['Username'] ) { if ( $user and $user['Username'] ) {
echo '<ul class="navbar-nav justify-content-center">'; echo '<ul class="navbar-nav align-self-start justify-content-center">';
echo getConsoleHTML(); echo getConsoleHTML();
echo getOptionsHTML(); echo getOptionsHTML();
echo getLogHTML(); echo getLogHTML();
echo getDevicesHTML(); echo getDevicesHTML();
echo getGroupsHTML(); echo getGroupsHTML($view);
echo getFilterHTML(); echo getFilterHTML($view, $filterQuery, $sortQuery, $limitQuery);
echo getCycleHTML(); echo getCycleHTML($view);
echo getMontageHTML(); echo getMontageHTML($view);
echo getMontageReviewHTML(); echo getMontageReviewHTML($view);
echo getRprtEvntAuditHTML(); echo getRprtEvntAuditHTML($view);
echo getHeaderFlipHTML(); echo getHeaderFlipHTML();
echo '</ul>'; echo '</ul>';
@ -323,10 +300,8 @@ function getNavBarHTML($reload = null) {
<nav class="navbar navbar-expand-md bg-dark justify-content-center p-0"> <nav class="navbar navbar-expand-md bg-dark justify-content-center p-0">
<div class="container-fluid" id="panel"<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down' ) ? 'style="display:none;"' : '' ?>> <div class="container-fluid" id="panel"<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down' ) ? 'style="display:none;"' : '' ?>>
<?php <?php
} // end reload null. Runs on full page load
if ( (!ZM_OPT_USE_AUTH) or $user ) { if ( (!ZM_OPT_USE_AUTH) or $user ) {
if ($reload == 'reload') ob_start();
// *** Build the statistics shown on the navigation bar *** // *** Build the statistics shown on the navigation bar ***
?> ?>
@ -335,60 +310,157 @@ function getNavBarHTML($reload = null) {
<?php echo getBandwidthHTML($bandwidth_options, $user) ?> <?php echo getBandwidthHTML($bandwidth_options, $user) ?>
</ul> </ul>
<ul class="navbar-nav justify-content-center"> <ul class="navbar-nav list-inline justify-content-center">
<?php <?php
echo getSysLoadHTML(); echo getSysLoadHTML();
echo getDbConHTML(); echo getDbConHTML();
echo getStorageHTML(); echo getStorageHTML();
echo getShmHTML(); echo getShmHTML();
echo getLogIconHTML();
?> ?>
</ul> </ul>
<ul id="Version" class="nav navbar-nav justify-content-end"> <ul id="Version" class="nav navbar-nav justify-content-end">
<?php <?php echo getZMVersionHTML() ?>
$versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':'';
echo getZMVersionHTML($versionClass);
?>
</ul> </ul>
</div> </div>
<?php echo getConsoleBannerHTML() ?>
<?php <?php
} // end if (!ZM_OPT_USE_AUTH) or $user ) } // end if (!ZM_OPT_USE_AUTH) or $user )
if ( $reload === null ) {
?> ?>
</div><!--panel--> </div><!-- End Collapsible Panel -->
</nav><!-- End Second Navbar --> </nav><!-- End Second Navbar -->
<nav class="navbar navbar-expand-md bg-dark justify-content-center p-0">
<?php echo getConsoleBannerHTML() ?>
</nav><!-- End Third Navbar -->
</div> </div>
<?php <?php
} // end if full page or reload } // end function getNormalNavBarHTML()
return ob_get_clean(); //
} // end function getNavBarHTML() // A new, slimmer navigation bar, permanently collapsed into a dropdown
//
function getCollapsedNavBarHTML($running, $user, $bandwidth_options, $view, $filterQuery, $sortQuery, $limitQuery) {
$status = runtimeStatus($running);
?>
<div class="fixed-top container-fluid p-0">
<nav class="navbar navbar-dark bg-dark px-1 flex-nowrap">
<div class="navbar-brand align-self-start px-0">
<?php echo getNavBrandHTML() ?>
</div>
<nav class="navbar navbar-expand-md align-self-start px-0">
<ul class="nav navbar-nav list-group px-0">
<?php
// *** Build the statistics shown on the navigation bar ***
if ( (!ZM_OPT_USE_AUTH) or $user ) {
?>
<div id="reload" class="collapse navbar-collapse px-0">
<ul id="Version" class="pr-2">
<?php echo getZMVersionHTML() ?>
</ul>
<ul id="Bandwidth" class="px-2">
<?php echo getBandwidthHTML($bandwidth_options, $user) ?>
</ul>
<?php
echo getSysLoadHTML();
echo getDbConHTML();
echo getStorageHTML();
echo getShmHTML();
echo getLogIconHTML();
?>
</div>
<?php
} // end if (!ZM_OPT_USE_AUTH) or $user )
?>
</nav>
<ul class="list-group list-group-horizontal ml-auto">
<?php
echo getAcctCircleHTML($user);
echo getStatusBtnHTML($status);
?>
</ul>
</ul>
<!-- the Navigation Bar Hamburger Button -->
<?php if ( (!ZM_OPT_USE_AUTH) or $user ) { ?>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#main-header-nav" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="navbar-toggler-icon"></span>
</button>
<?php } ?>
<div style="background-color:#485460" class="dropdown-menu dropdown-menu-right px-3" id="main-header-nav">
<?php
if ( $user and $user['Username'] ) {
echo '<ul class="navbar-nav">';
echo getConsoleHTML();
echo getOptionsHTML();
echo getLogHTML();
echo getDevicesHTML();
echo getGroupsHTML($view);
echo getFilterHTML($view,$filterQuery,$sortQuery,$limitQuery);
echo getCycleHTML($view);
echo getMontageHTML($view);
echo getMontageReviewHTML($view);
echo getRprtEvntAuditHTML($view);
echo '</ul>';
}
?>
</div>
</nav><!-- End First Navbar -->
<nav class="navbar navbar-expand-md bg-dark justify-content-center p-0">
<?php echo getConsoleBannerHTML() ?>
</nav><!-- End Second Navbar -->
</div>
<?php
} // End function getCollapsedNavBarHTML
// Returns the html representing the current unix style system load // Returns the html representing the current unix style system load
function getSysLoadHTML() { function getSysLoadHTML() {
$result = '';
echo '<li class="Load nav-item mx-2">'.PHP_EOL; $result .= '<li id="getSysLoadHTML" class="Load nav-item mx-2">'.PHP_EOL;
echo '<i class="material-icons md-18">trending_up</i>'.PHP_EOL; $result .= '<i class="material-icons md-18">trending_up</i>'.PHP_EOL;
echo '&nbsp;'.translate('Load').': '.getLoad().PHP_EOL; $result .= '&nbsp;'.translate('Load').': '.getLoad().PHP_EOL;
echo '</li>'.PHP_EOL; $result .= '</li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the current number of connections made to the database // Returns the html representing the current number of connections made to the database
function getDbConHTML() { function getDbConHTML() {
$result = '';
$connections = dbFetchOne('SHOW status WHERE variable_name=\'threads_connected\'', 'Value'); $connections = dbFetchOne('SHOW status WHERE variable_name=\'threads_connected\'', 'Value');
$max_connections = dbFetchOne('SHOW variables WHERE variable_name=\'max_connections\'', 'Value'); $max_connections = dbFetchOne('SHOW variables WHERE variable_name=\'max_connections\'', 'Value');
$percent_used = $max_connections ? 100 * $connections / $max_connections : 100; $percent_used = $max_connections ? 100 * $connections / $max_connections : 100;
$class = ( $percent_used > 90 ) ? 'text-warning' : ''; $class = ( $percent_used > 90 ) ? ' text-warning' : '';
echo '<li class="nav-item mx-2 ' .$class. '">'.PHP_EOL; $result .= '<li id="getDbConHTML" class="nav-item dropdown mx-2' .$class. '">'.PHP_EOL;
echo '<i class="material-icons md-18 mr-1">storage</i>'.PHP_EOL; $result .= '<i class="material-icons md-18 mr-1">storage</i>'.PHP_EOL;
echo translate('DB'). ': ' .$connections. '/' .$max_connections.PHP_EOL; $result .= translate('DB'). ': ' .$connections. '/' .$max_connections.PHP_EOL;
echo '</li>'.PHP_EOL; $result .= '</li>'.PHP_EOL;
return $result;
} }
// Returns the html representing up to 4 storage areas and their current capacity // Returns an html dropdown showing capacity of all storage areas
function getStorageHTML() { function getStorageHTML() {
$result='';
$func = function($S) { $func = function($S) {
$class = ''; $class = '';
@ -399,32 +471,43 @@ function getStorageHTML() {
} }
$title = human_filesize($S->disk_used_space()) . ' of ' . human_filesize($S->disk_total_space()). $title = human_filesize($S->disk_used_space()) . ' of ' . human_filesize($S->disk_total_space()).
( ( $S->disk_used_space() != $S->event_disk_space() ) ? ' ' .human_filesize($S->event_disk_space()) . ' used by events' : '' ); ( ( $S->disk_used_space() != $S->event_disk_space() ) ? ' ' .human_filesize($S->event_disk_space()) . ' used by events' : '' );
return '<span class="ml-1 '.$class.'" title="'.$title.'">'.$S->Name() . ': ' . $S->disk_usage_percent().'%' . '</span>'; return '<a class="dropdown-item '.$class.'" title="'.$title.'" href="?view=options&amp;tab=storage">'.$S->Name() . ': ' . $S->disk_usage_percent().'%' . '</a>';
}; };
$storage_areas = ZM\Storage::find(array('Enabled'=>true)); $storage_areas = ZM\Storage::find(array('Enabled'=>true));
$num_storage_areas = count($storage_areas); $num_storage_areas = count($storage_areas);
$storage_paths = null;
$storage_areas_with_no_server_id = array(); $full_warning = 0;
$full_error = 0;
foreach ( $storage_areas as $area ) { foreach ( $storage_areas as $area ) {
$storage_paths[$area->Path()] = $area; if ( $area->disk_usage_percent() > 98 ) { $full_error++; continue; }
if ( ! $area->ServerId() ) { if ( $area->disk_usage_percent() > 90 ) $full_warning++;
$storage_areas_with_no_server_id[] = $area;
}
} }
echo '<li class="nav-item mx-2">'.translate('Storage').':'; $class = '';
if ( $full_error ) {
if ( $num_storage_areas > 4 ) { $class = 'text-danger';
$storage_areas = $storage_areas_with_no_server_id; } else if ( $full_warning ) {
} else { $class = 'text-warning';
echo implode(', ', array_map($func, $storage_areas));
} }
echo '</li>'.PHP_EOL;
$result .= '<li id="getStorageHTML" class="nav-item dropdown mx-2">'.PHP_EOL;
$result .= '<a class="dropdown-toggle mr-2 '.$class.'" href="#" id="dropdown_storage" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="material-icons md-18 mr-1">folder_shared</i>Storage</a>'.PHP_EOL;
$result .= '<div class="dropdown-menu" aria-labelledby="dropdown_storage">'.PHP_EOL;
foreach ( $storage_areas as $area ) {
$result .= $func($area).PHP_EOL;
}
$result .= '</div>'.PHP_EOL;
$result .= '</li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the current capacity of mapped memory filesystem (usually /dev/shm) // Returns the html representing the current capacity of mapped memory filesystem (usually /dev/shm)
function getShmHTML() { function getShmHTML() {
$result = '';
$shm_percent = getDiskPercent(ZM_PATH_MAP); $shm_percent = getDiskPercent(ZM_PATH_MAP);
$shm_total_space = disk_total_space(ZM_PATH_MAP); $shm_total_space = disk_total_space(ZM_PATH_MAP);
$shm_used = $shm_total_space - disk_free_space(ZM_PATH_MAP); $shm_used = $shm_total_space - disk_free_space(ZM_PATH_MAP);
@ -435,117 +518,223 @@ function getShmHTML() {
} else if ( $shm_percent > 90 ) { } else if ( $shm_percent > 90 ) {
$class = 'text-warning'; $class = 'text-warning';
} }
echo ' <li class="nav-item ' .$class. '" title="' .human_filesize($shm_used). ' of ' .human_filesize($shm_total_space). '">' .ZM_PATH_MAP. ': '.$shm_percent.'%</li>'.PHP_EOL; $result .= ' <li id="getShmHTML" class="nav-item dropdown mx-2' .$class. '" title="' .human_filesize($shm_used). ' of ' .human_filesize($shm_total_space). '">' .ZM_PATH_MAP. ': '.$shm_percent.'%</li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the optional web console banner text // Returns the html representing the optional web console banner text
function getConsoleBannerHTML() { function getConsoleBannerHTML() {
$result = '';
if ( defined('ZM_WEB_CONSOLE_BANNER') and ZM_WEB_CONSOLE_BANNER != '' ) { if ( defined('ZM_WEB_CONSOLE_BANNER') and ZM_WEB_CONSOLE_BANNER != '' ) {
echo '<h3 id="development">'.validHtmlStr(ZM_WEB_CONSOLE_BANNER).'</h3>'; $result .= '<h2 id="getConsoleBannerHTML">'.validHtmlStr(ZM_WEB_CONSOLE_BANNER).'</h2>';
} }
return $result;
} }
// Returns the html representing the current high,medium,low bandwidth setting // Returns the html representing the current high,medium,low bandwidth setting
function getBandwidthHTML($bandwidth_options,$user) { function getBandwidthHTML($bandwidth_options, $user) {
echo '<li class="nav-item">'.makePopupLink( '?view=bandwidth', 'zmBandwidth', 'bandwidth', "<i class='material-icons md-18'>network_check</i>&nbsp;".$bandwidth_options[$_COOKIE['zmBandwidth']] . ' ', ($user && $user['MaxBandwidth'] != 'low' )).'</li>'.PHP_EOL;
# Limit available options to what are available in user
if ( $user && !empty($user['MaxBandwidth']) ) {
if ( $user['MaxBandwidth'] == 'low' ) {
unset($bandwidth_options['high']);
unset($bandwidth_options['medium']);
} else if ( $user['MaxBandwidth'] == 'medium' ) {
unset($bandwidth_options['high']);
}
}
$result = '<li id="getBandwidthHTML" class="nav-item dropdown mx-2">'.PHP_EOL;
$result .= '<a class="dropdown-toggle mr-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="dropdown_bandwidth"><i class="material-icons md-18 mr-1">network_check</i>'.translate($bandwidth_options[$_COOKIE['zmBandwidth']]).'</a>'.PHP_EOL;
$result .= '<div class="dropdown-menu" aria-labelledby="dropdown_bandwidth">'.PHP_EOL;
if ( count($bandwidth_options) > 1 ) {
if ( isset($bandwidth_options['high']) )
$result .= '<a data-pdsa-dropdown-val="high" class="dropdown-item" href="#">' .translate('High'). '</a>'.PHP_EOL;
if ( isset($bandwidth_options['medium']) )
$result .= '<a data-pdsa-dropdown-val="medium" class="dropdown-item" href="#">' .translate('Medium'). '</a>'.PHP_EOL;
# low is theoretically always available
$result .= '<a data-pdsa-dropdown-val="low" class="dropdown-item" href="#">' .translate('Low'). '</a>'.PHP_EOL;
}
$result .= '</div>'.PHP_EOL;
$result .= '</li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the version of ZoneMinder // Returns the html representing the version of ZoneMinder
function getZMVersionHTML($versionClass) { function getZMVersionHTML() {
echo '<li class="nav-item">'.makePopupLink( '?view=version', 'zmVersion', 'version', '<span class="version '.$versionClass.'">v'.ZM_VERSION.'</span>', canEdit('System') ).'</li>'.PHP_EOL; $result = '';
$content = '';
if ( ZM_DYN_DB_VERSION && (ZM_DYN_DB_VERSION != ZM_VERSION) ) { // Must upgrade before proceeding
$class = 'text-danger';
$tt_text = translate('RunLocalUpdate');
$content = 'v'.ZM_VERSION.PHP_EOL;
} else if ( verNum( ZM_DYN_LAST_VERSION ) <= verNum( ZM_VERSION ) ) { // No update needed
$class = ''; // Don't change the text color under normal conditions
$tt_text = translate('UpdateNotNecessary');
$content = 'v'.ZM_VERSION.PHP_EOL;
} else if ( canEdit('System') ) { // An update is available and the user is an administrator
$class = 'text-warning';
$tt_text = translate('UpdateAvailable');
$content = '<a class="dropdown ' .$class. '" data-toggle="dropdown" href="#" id="dropdown_reminder">v' .ZM_VERSION. '</a>'.PHP_EOL;
$content .= '<div class="dropdown-menu" aria-labelledby="dropdown_reminder">'.PHP_EOL;
$content .= '<h6 class="dropdown-header">' .translate('UpdateAvailable'). '</h6>'.PHP_EOL;
$content .= '<a class="dropdown-item" data-pdsa-dropdown-val="ignore" href="#">' .translate('VersionIgnore'). '</a>'.PHP_EOL;
$content .= '<a class="dropdown-item" data-pdsa-dropdown-val="hour" href="#">' .translate('VersionRemindHour'). '</a>'.PHP_EOL;
$content .= '<a class="dropdown-item" data-pdsa-dropdown-val="day" href="#">' .translate('VersionRemindDay'). '</a>'.PHP_EOL;
$content .= '<a class="dropdown-item" data-pdsa-dropdown-val="week" href="#">' .translate('VersionRemindWeek'). '</a>'.PHP_EOL;
$content .= '<a class="dropdown-item" data-pdsa-dropdown-val="month" href="#">' .translate('VersionRemindMonth'). '</a>'.PHP_EOL;
$content .= '<a class="dropdown-item" data-pdsa-dropdown-val="never" href="#">' .translate('VersionRemindNever'). '</a>'.PHP_EOL;
$content .= '</div>'.PHP_EOL;
} else { // An update is available and the user is NOT an administrator
$class = 'text-warning';
$tt_text = translate('UpdateAvailable');
$content = 'v'.ZM_VERSION.PHP_EOL;
}
$result .= '<li id="getZMVersionHTML" class="nav-item dropdown ' .$class. '" data-placement="bottom" title="' .$tt_text. '">'.PHP_EOL;
$result .= $content;
$result .= '</li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the ZoneMinder logo // Returns the html representing the ZoneMinder logo and about menu
function getNavBrandHTML() { function getNavBrandHTML() {
echo '<a href="' .validHtmlStr(ZM_HOME_URL). '" target="' .validHtmlStr(ZM_WEB_TITLE). '">' .ZM_HOME_CONTENT. '</a>'.PHP_EOL; $result = '';
if ( ZM_HOME_ABOUT ) {
$result .= '<a id="getNavBrandHTML" class="dropdown" data-toggle="dropdown" href="#">ZoneMinder</a>'.PHP_EOL;
$result .= '<ul style="background-color:#485460" class="dropdown-menu">'.PHP_EOL;
$result .= '<li><a class="dropdown-item" href="https://zoneminder.com/" target="_blank">ZoneMinder</a></li>'.PHP_EOL;
$result .= '<li><a class="dropdown-item" href="https://zoneminder.readthedocs.io/en/stable/" target="_blank">Documentation</a></li>'.PHP_EOL;
$result .= '<li><a class="dropdown-item" href="https://forums.zoneminder.com/" target="_blank">Support</a></li>'.PHP_EOL;
$result .= '</ul>'.PHP_EOL;
} else {
$result .= '<a id="getNavBrandHTML" href="' .validHtmlStr(ZM_HOME_URL). '" target="' .validHtmlStr(ZM_WEB_TITLE). '">' .ZM_HOME_CONTENT. '</a>'.PHP_EOL;
}
return $result;
} }
// Returns the html representing the Console menu item // Returns the html representing the Console menu item
function getConsoleHTML() { function getConsoleHTML() {
$result = '';
if ( canView('Monitors') ) { if ( canView('Monitors') ) {
echo '<li class="nav-item"><a class="nav-link" href="?view=console">'.translate('Console').'</a></li>'.PHP_EOL; $result .= '<li id="getConsoleHTML" class="nav-item dropdown"><a class="nav-link" href="?view=console">'.translate('Console').'</a></li>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the Options menu item // Returns the html representing the Options menu item
function getOptionsHTML() { function getOptionsHTML() {
$result = '';
if ( canView('System') ) { if ( canView('System') ) {
echo '<li class="nav-item"><a class="nav-link" href="?view=options">'.translate('Options').'</a></li>'.PHP_EOL; $result .= '<li id="getOptionsHTML" class="nav-item dropdown"><a class="nav-link" href="?view=options">'.translate('Options').'</a></li>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the Log menu item // Returns the html representing the Log menu item
function getLogHTML() { function getLogHTML() {
$result = '';
if ( canView('System') ) { if ( canView('System') ) {
if ( ZM\logToDatabase() > ZM\Logger::NOLOG ) { if ( ZM\logToDatabase() > ZM\Logger::NOLOG ) {
if ( ! ZM_RUN_AUDIT ) {
# zmaudit can clean the logs, but if we aren't running it, then we should clean them regularly
if ( preg_match('/^\d+$/', ZM_LOG_DATABASE_LIMIT) ) {
# Number of lines, instead of an interval
$rows = dbFetchOne('SELECT Count(*) AS `Rows` FROM `Logs`', 'Rows');
if ( $rows > ZM_LOG_DATABASE_LIMIT ) {
dbQuery('DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?', array($rows - ZM_LOG_DATABASE_LIMIT));
}
} else if ( preg_match('/^\d\s*(hour|minute|day|week|month|year)$/', ZM_LOG_DATABASE_LIMIT, $matches) ) {
dbQuery('DELETE FROM `Logs` WHERE `TimeKey` < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100');
} else {
ZM\Error('Potentially invalid value for ZM_LOG_DATABASE_LIMIT: ' . ZM_LOG_DATABASE_LIMIT);
}
}
$logstate = logState(); $logstate = logState();
$class = ($logstate == 'ok') ? 'text-success' : ($logstate == 'alert' ? 'text-warning' : (($logstate == 'alarm' ? 'text-danger' : ''))); $class = ($logstate == 'ok') ? 'text-success' : ($logstate == 'alert' ? 'text-warning' : (($logstate == 'alarm' ? 'text-danger' : '')));
echo '<li class="nav-item">'.makePopupLink('?view=log', 'zmLog', 'log', '<span class="nav-link '.$class.'">'.translate('Log').'</span></li>').PHP_EOL; $result .= '<li id="getLogHTML" class="nav-item dropdown mx-2">'.makePopupLink('?view=log', 'zmLog', 'log', '<span class="nav-link '.$class.'">'.translate('Log').'</span>').'</li>'.PHP_EOL;
} }
} }
return $result;
}
// Returns the html representing the log icon
function getLogIconHTML() {
$result = '';
if ( canView('System') ) {
if ( ZM\logToDatabase() > ZM\Logger::NOLOG ) {
$logstate = logState();
$class = ( $logstate == 'alert' ) ? 'text-warning' : (( $logstate == 'alarm' ) ? 'text-danger' : '');
$result .= '<li id="getLogIconHTML" class="nav-item dropdown">'.
makePopupLink('?view=log', 'zmLog', 'log', '<span class="mx-1 ' .$class. '"><i class="material-icons md-18">report</i>'.translate('Log').'</span>').
'</li>'.PHP_EOL;
}
}
return $result;
} }
// Returns the html representing the X10 Devices menu item // Returns the html representing the X10 Devices menu item
function getDevicesHTML() { function getDevicesHTML() {
$result = '';
if ( ZM_OPT_X10 && canView('Devices') ) { if ( ZM_OPT_X10 && canView('Devices') ) {
echo '<li class="nav-item"><a class="nav-link" href="?view=devices">Devices</a></li>'.PHP_EOL; $result .= '<li id="getDevicesHTML" class="nav-item dropdown"><a class="nav-link" href="?view=devices">Devices</a></li>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the Groups menu item // Returns the html representing the Groups menu item
function getGroupsHTML() { function getGroupsHTML($view) {
global $view; $result = '';
$class = $view == 'groups' ? 'selected' : '';
echo '<li class="nav-item"><a class="nav-link" href="?view=groups" class="' .$class. '">'. translate('Groups') .'</a></li>'.PHP_EOL; $class = $view == 'groups' ? ' selected' : '';
$result .= '<li id="getGroupsHTML" class="nav-item dropdown"><a class="nav-link'.$class.'" href="?view=groups">'. translate('Groups') .'</a></li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the Filter menu item // Returns the html representing the Filter menu item
function getFilterHTML() { function getFilterHTML($view, $filterQuery, $sortQuery, $limitQuery) {
global $view; $result = '';
global $filterQuery;
global $sortQuery;
global $limitQuery;
$class = $view == 'filter' ? 'selected' : ''; $class = $view == 'filter' ? ' selected' : '';
echo '<li class="nav-item"><a class="nav-link" href="?view=filter'.$filterQuery.$sortQuery.$limitQuery.'" class="'.$class.'">'.translate('Filters').'</a></li>'.PHP_EOL; $result .= '<li id="getFilterHTML" class="nav-item dropdown"><a class="nav-link'.$class.'" href="?view=filter'.$filterQuery.$sortQuery.$limitQuery.'">'.translate('Filters').'</a></li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the Cycle menu item // Returns the html representing the Cycle menu item
function getCycleHTML() { function getCycleHTML($view) {
global $view; $result = '';
if ( canView('Stream') ) { if ( canView('Stream') ) {
$class = $view == 'cycle' ? 'selected' : ''; $class = $view == 'cycle' ? ' selected' : '';
echo '<li class="nav-item"><a class="nav-link" href="?view=cycle" class="' .$class. '">' .translate('Cycle'). '</a></li>'.PHP_EOL; $result .= '<li id="getCycleHTML" class="nav-item dropdown"><a class="nav-link'.$class.'" href="?view=cycle">' .translate('Cycle'). '</a></li>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the Montage menu item // Returns the html representing the Montage menu item
function getMontageHTML() { function getMontageHTML($view) {
global $view; $result = '';
if ( canView('Stream') ) { if ( canView('Stream') ) {
$class = $view == 'cycle' ? 'selected' : ''; $class = $view == 'cycle' ? ' selected' : '';
echo '<li class="nav-item"><a class="nav-link" href="?view=montage" class="' .$class. '">' .translate('Montage'). '</a></li>'.PHP_EOL; $result .= '<li id="getMontageHTML" class="nav-item dropdown"><a class="nav-link'.$class.'" href="?view=montage">' .translate('Montage'). '</a></li>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the MontageReview menu item // Returns the html representing the MontageReview menu item
function getMontageReviewHTML() { function getMontageReviewHTML($view) {
global $view; $result = '';
if ( canView('Events') ) { if ( canView('Events') ) {
if ( isset($_REQUEST['filter']['Query']['terms']['attr']) ) { if ( isset($_REQUEST['filter']['Query']['terms']['attr']) ) {
$terms = $_REQUEST['filter']['Query']['terms']; $terms = $_REQUEST['filter']['Query']['terms'];
@ -562,63 +751,92 @@ function getMontageReviewHTML() {
} }
} }
$live = isset($montageReviewQuery) ? '&fit=1'.$montageReviewQuery.'&live=0' : ''; $live = isset($montageReviewQuery) ? '&fit=1'.$montageReviewQuery.'&live=0' : '';
$class = $view == 'montagereview' ? 'selected' : ''; $class = $view == 'montagereview' ? ' selected' : '';
echo '<li class="nav-item"><a class="nav-link" href="?view=montagereview' .$live. '" class="' .$class. '">' .translate('MontageReview'). '</a></li>'.PHP_EOL; $result .= '<li id="getMontageReviewHTML" class="nav-item dropdown"><a class="nav-link'.$class.'" href="?view=montagereview' .$live. '">'.translate('MontageReview').'</a></li>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the Audit Events Report menu item // Returns the html representing the Audit Events Report menu item
function getRprtEvntAuditHTML() { function getRprtEvntAuditHTML($view) {
global $view; $result = '';
if ( canView('Events') ) { if ( canView('Events') ) {
$class = $view == 'report_event_audit' ? 'selected' : ''; $class = $view == 'report_event_audit' ? ' selected' : '';
echo '<li class="nav-item"><a class="nav-link" href="?view=report_event_audit" class="' .$class. '">' .translate('ReportEventAudit'). '</a></li>'.PHP_EOL; $result .= '<li id="getRprtEvntAuditHTML" class="nav-item dropdown"><a class="nav-link'.$class.'" href="?view=report_event_audit">'.translate('ReportEventAudit').'</a></li>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the header collapse toggle menu item // Returns the html representing the header collapse toggle menu item
function getHeaderFlipHTML() { function getHeaderFlipHTML() {
$result = '';
$header = ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down') ? 'down' : 'up'; $header = ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down') ? 'down' : 'up';
echo '<li class="nav-item"><a class="nav-link" href="#"><i id="flip" class="material-icons md-18">keyboard_arrow_' .$header. '</i></a></li>'.PHP_EOL; $result .= '<li id="getHeaderFlipHTML" class="nav-item dropdown"><a class="nav-link" href="#"><i id="flip" class="material-icons md-18">keyboard_arrow_' .$header. '</i></a></li>'.PHP_EOL;
return $result;
} }
// Returns the html representing the logged in user name and avatar // Returns the html representing the logged in user name and avatar
function getAcctCircleHTML($user=null) { function getAcctCircleHTML($user=null) {
$result = '';
if ( ZM_OPT_USE_AUTH and $user ) { if ( ZM_OPT_USE_AUTH and $user ) {
echo '<p class="navbar-text mx-3">'.PHP_EOL; $result .= '<p id="getAcctCircleHTML" class="navbar-text mr-2">'.PHP_EOL;
echo '<i class="material-icons">account_circle</i>'; $result .= makePopupLink('?view=logout', 'zmLogout', 'logout',
echo makePopupLink('?view=logout', 'zmLogout', 'logout', $user['Username'], (ZM_AUTH_TYPE == 'builtin') ).PHP_EOL; '<i class="material-icons">account_circle</i> '. $user['Username'],
echo '</p>'.PHP_EOL; (ZM_AUTH_TYPE == 'builtin') ).PHP_EOL;
$result .= '</p>'.PHP_EOL;
} }
return $result;
} }
// Returns the html representing the runtime status button // Returns the html representing the runtime status button
function getStatusBtnHTML($status) { function getStatusBtnHTML($status) {
$result = '';
if ( canEdit('System') ) { if ( canEdit('System') ) {
echo '<li class="nav-item">'.PHP_EOL; //$result .= '<li class="nav-item dropdown">'.PHP_EOL;
echo '<form class="form-inline">'.PHP_EOL; $result .= '<form id="getStatusBtnHTML" class="form-inline">'.PHP_EOL;
echo '<button type="button" class="mx-3 btn btn-default navbar-btn" data-toggle="modal" data-target="#modalState">' .$status. '</button>'.PHP_EOL; $result .= '<button type="button" class="btn btn-default navbar-btn" data-toggle="modal" data-target="#modalState">' .$status. '</button>'.PHP_EOL;
echo '</form>'.PHP_EOL; $result .= '</form>'.PHP_EOL;
echo '</li>'.PHP_EOL; //$result .= '</li>'.PHP_EOL;
if ( ZM_SYSTEM_SHUTDOWN ) { if ( ZM_SYSTEM_SHUTDOWN ) {
echo '<p class="navbar-text">'.PHP_EOL; $result .= '<p class="navbar-text">'.PHP_EOL;
echo makePopupLink('?view=shutdown', 'zmShutdown', 'shutdown', '<i class="material-icons md-18">power_settings_new</i>' ).PHP_EOL; $result .= makePopupLink('?view=shutdown', 'zmShutdown', 'shutdown', '<i class="material-icons md-18">power_settings_new</i>' ).PHP_EOL;
echo '</p>'.PHP_EOL; $result .= '</p>'.PHP_EOL;
} }
} else if ( canView('System') ) { } else if ( canView('System') ) {
echo '<p class="navbar-text">'.PHP_EOL; $result .= '<p id="getStatusBtnHTML" class="navbar-text">'.PHP_EOL;
echo $status.PHP_EOL; $result .= $status.PHP_EOL;
echo '</p>'.PHP_EOL; $result .= '</p>'.PHP_EOL;
} }
return $result;
}
function runtimeStatus($running=null) {
if ( $running == null )
$running = daemonCheck();
if ( $running ) {
$state = dbFetchOne('SELECT Name FROM States WHERE isActive=1', 'Name');
if ( $state == 'default' )
$state = '';
}
return $running ? ($state ? $state : translate('Running')) : translate('Stopped');
} }
function xhtmlFooter() { function xhtmlFooter() {
global $cspNonce; global $cspNonce;
global $view; global $view;
global $skin; global $skin;
global $running;
if ( canEdit('System') ) { if ( canEdit('System') ) {
include("skins/$skin/views/state.php"); include("skins/$skin/views/state.php");
} }

View File

@ -21,7 +21,6 @@
// This file should only contain static JavaScript and no php. // This file should only contain static JavaScript and no php.
// Use skin.js.php for JavaScript that need pre-processing // Use skin.js.php for JavaScript that need pre-processing
// //
var popupOptions = "resizable,scrollbars,status=no,toolbar=yes"; var popupOptions = "resizable,scrollbars,status=no,toolbar=yes";
function checkSize() { function checkSize() {
@ -313,9 +312,64 @@ if ( currentView != 'none' && currentView != 'login' ) {
$j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON. $j.ajaxSetup({timeout: AJAX_TIMEOUT}); //sets timeout for all getJSON.
$j(document).ready(function() { $j(document).ready(function() {
// Trigger autorefresh of the widget bar stats on the navbar
if ( $j('.navbar').length ) { if ( $j('.navbar').length ) {
setInterval(getNavBar, navBarRefresh); setInterval(getNavBar, navBarRefresh);
} }
// Workaround Bootstrap-Mootools conflict
var bootstrapLoaded = (typeof $j().carousel == 'function');
var mootoolsLoaded = (typeof MooTools != 'undefined');
if (bootstrapLoaded && mootoolsLoaded) {
Element.implement({
hide: function() {
return this;
},
show: function(v) {
return this;
},
slide: function(v) {
return this;
}
});
}
// Update zmBandwidth cookie when the user makes a selection from the dropdown
bwClickFunction();
// Update update reminders when the user makes a selection from the dropdown
reminderClickFunction();
// Manage the widget bar minimize chevron
$j("#flip").click(function() {
$j("#panel").slideToggle("slow");
var flip = $j("#flip");
if ( flip.html() == 'keyboard_arrow_up' ) {
flip.html('keyboard_arrow_down');
Cookie.write('zmHeaderFlip', 'down', {duration: 10*365} );
} else {
flip.html('keyboard_arrow_up');
Cookie.write('zmHeaderFlip', 'up', {duration: 10*365} );
}
});
// Manage the web console filter bar minimize chevron
$j("#fbflip").click(function() {
$j("#fbpanel").slideToggle("slow");
var fbflip = $j("#fbflip");
if ( fbflip.html() == 'keyboard_arrow_up' ) {
fbflip.html('keyboard_arrow_down');
Cookie.write('zmFilterBarFlip', 'down', {duration: 10*365} );
} else {
fbflip.html('keyboard_arrow_up');
Cookie.write('zmFilterBarFlip', 'up', {duration: 10*365} );
$j('.chosen').chosen("destroy");
$j('.chosen').chosen();
}
});
// Autoclose the hamburger button if the end user clicks outside the button
$j(document).click(function(event) {
var target = $j(event.target);
var _mobileMenuOpen = $j("#main-header-nav").hasClass("show");
if (_mobileMenuOpen === true && !target.hasClass("navbar-toggler")) {
$j("button.navbar-toggler").click();
}
});
}); });
function getNavBar() { function getNavBar() {
@ -338,7 +392,13 @@ if ( currentView != 'none' && currentView != 'login' ) {
auth_hash = data.auth; auth_hash = data.auth;
} }
} }
$j('#reload').replaceWith(data.message); // iterate through all the keys then update each element id with the same name
for (var key of Object.keys(data)) {
if ( key == "auth" ) continue;
if ( $j('#'+key).hasClass("show") ) continue; // don't update if the user has the dropdown open
if ( $j('#'+key).length ) $j('#'+key).replaceWith(data[key]);
if ( key == 'getBandwidthHTML' ) bwClickFunction();
}
} }
} }
@ -575,3 +635,33 @@ function setButtonState(element_id, butClass) {
console.log('Element was null or not found in setButtonState. id:'+element_id); console.log('Element was null or not found in setButtonState. id:'+element_id);
} }
} }
function setCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function delCookie(name) {
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}
function bwClickFunction() {
$j("#dropdown_bandwidth a").click(function() {
var bwval = $j(this).data('pdsa-dropdown-val');
setCookie("zmBandwidth", bwval, 3600);
getNavBar();
});
}
function reminderClickFunction() {
$j("#dropdown_reminder a").click(function() {
var option = $j(this).data('pdsa-dropdown-val');
$j.getJSON(thisUrl + '?view=version&action=version&option=' + option);
window.location.reload(true); //Do a full refresh to update ZM_DYN_LAST_VERSION
});
}

View File

@ -210,7 +210,7 @@ getBodyTopHTML();
<?php <?php
ob_start(); ob_start();
?> ?>
<div class="table-responsive pt-2"> <div class="table-responsive-sm pt-2">
<table class="table table-striped table-hover table-condensed consoleTable"> <table class="table table-striped table-hover table-condensed consoleTable">
<thead class="thead-highlight"> <thead class="thead-highlight">
<tr> <tr>
@ -327,7 +327,7 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
echo '<td class="colSource">'. makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$source_class.'">'.validHtmlStr($Monitor->Source()).'</span>', canEdit('Monitors') ).'</td>'; echo '<td class="colSource">'. makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$source_class.'">'.validHtmlStr($Monitor->Source()).'</span>', canEdit('Monitors') ).'</td>';
if ( $show_storage_areas ) { if ( $show_storage_areas ) {
?> ?>
<td class="colStorage"><?php if ( isset($StorageById[$monitor['StorageId']]) ) { echo validHtmlStr($StorageById[$monitor['StorageId']]->Name()); } ?></td> <td class="colStorage"><?php echo isset($StorageById[$monitor['StorageId']]) ? validHtmlStr($StorageById[$monitor['StorageId']]->Name()) : ($monitor['StorageId']?'<span class="error">Deleted '.$monitor['StorageId'].'</span>' : '') ?></td>
<?php <?php
} }

View File

@ -161,11 +161,11 @@ xhtmlHeaders(__FILE__, translate('CycleWatch'));
</div> </div>
<div class="container-fluid"> <div class="container-fluid">
<div class="row" id="content"> <div class="row" id="content">
<div class="col-sm-2 sidebar"> <div class="col-sm-2 sidebar">
<ul class="nav nav-pills nav-stacked"> <ul class="nav flex-column">
<?php <?php
foreach ( $monitors as $m ) { foreach ( $monitors as $m ) {
echo '<li'.( $m->Id() == $monitor->Id() ? ' class="active"' : '' ).'><a href="?view=cycle&amp;mid='.$m->Id().'">'.$m->Name().'</a></li>'; echo '<li class="nav-item"><a class="nav-link'.( $m->Id() == $monitor->Id() ? ' active' : '' ).'" href="?view=cycle&amp;mid='.$m->Id().'">'.$m->Name().'</a></li>';
} }
?> ?>
</ul> </ul>

View File

@ -68,9 +68,9 @@ if ( !empty($page) ) {
$limitLeft = $limit - $limitStart; $limitLeft = $limit - $limitStart;
$limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft; $limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft;
} }
$eventsSql .= " limit $limitStart, $limitAmount"; $eventsSql .= " LIMIT $limitStart, $limitAmount";
} elseif ( !empty($limit) ) { } elseif ( !empty($limit) ) {
$eventsSql .= ' limit 0, '.$limit; $eventsSql .= ' LIMIT 0, '.$limit;
} }
$maxShortcuts = 5; $maxShortcuts = 5;
@ -138,7 +138,7 @@ if ( $pages > 1 ) {
<input type="hidden" name="sort_field" value="<?php echo validHtmlStr($_REQUEST['sort_field']) ?>"/> <input type="hidden" name="sort_field" value="<?php echo validHtmlStr($_REQUEST['sort_field']) ?>"/>
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/> <input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
<input type="hidden" name="limit" value="<?php echo $limit ?>"/> <input type="hidden" name="limit" value="<?php echo $limit ?>"/>
<div class="table-responsive"> <div class="table-responsive-sm">
<table id="contentTable" class="major"> <table id="contentTable" class="major">
<tbody> <tbody>
<?php <?php
@ -157,34 +157,35 @@ while ( $event_row = dbFetchNext($results) ) {
?> ?>
<tr> <tr>
<th class="colId"><a href="<?php echo sortHeader('Id') ?>"><?php echo translate('Id') ?><?php echo sortTag('Id') ?></a></th> <th class="colId"><a href="<?php echo sortHeader('Id') ?>"><?php echo translate('Id') ?><?php echo sortTag('Id') ?></a></th>
<th class="colName"><a href="<?php echo sortHeader('Name') ?>"><?php echo translate('Name') ?><?php echo sortTag('Name') ?></a></th> <th class="colName px-1"><a href="<?php echo sortHeader('Name') ?>"><?php echo translate('Name') ?><?php echo sortTag('Name') ?></a></th>
<th class="colMonitor"><a href="<?php echo sortHeader('MonitorName') ?>"><?php echo translate('Monitor') ?><?php echo sortTag('MonitorName') ?></a></th> <th class="colMonitor px-1"><a href="<?php echo sortHeader('MonitorName') ?>"><?php echo translate('Monitor') ?><?php echo sortTag('MonitorName') ?></a></th>
<th class="colCause"><a href="<?php echo sortHeader('Cause') ?>"><?php echo translate('Cause') ?><?php echo sortTag('Cause') ?></a></th> <th class="colCause px-1"><a href="<?php echo sortHeader('Cause') ?>"><?php echo translate('Cause') ?><?php echo sortTag('Cause') ?></a></th>
<th class="colTime"><a href="<?php echo sortHeader('StartTime') ?>"><?php echo translate('Time') ?><?php echo sortTag('StartTime') ?></a></th> <th class="colStartTime px-1"><a href="<?php echo sortHeader('StartTime') ?>"><?php echo translate('AttrStartTime') ?><?php echo sortTag('StartTime') ?></a></th>
<th class="colDuration"><a href="<?php echo sortHeader('Length') ?>"><?php echo translate('Duration') ?><?php echo sortTag('Length') ?></a></th> <th class="colEndTime px-1"><a href="<?php echo sortHeader('EndTime') ?>"><?php echo translate('AttrEndTime') ?><?php echo sortTag('EndTime') ?></a></th>
<th class="colFrames"><a href="<?php echo sortHeader('Frames') ?>"><?php echo translate('Frames') ?><?php echo sortTag('Frames') ?></a></th> <th class="colDuration px-1"><a href="<?php echo sortHeader('Length') ?>"><?php echo translate('Duration') ?><?php echo sortTag('Length') ?></a></th>
<th class="colAlarmFrames"><a href="<?php echo sortHeader('AlarmFrames') ?>"><?php echo translate('AlarmBrFrames') ?><?php echo sortTag('AlarmFrames') ?></a></th> <th class="colFrames px-1"><a href="<?php echo sortHeader('Frames') ?>"><?php echo translate('Frames') ?><?php echo sortTag('Frames') ?></a></th>
<th class="colTotScore"><a href="<?php echo sortHeader('TotScore') ?>"><?php echo translate('TotalBrScore') ?><?php echo sortTag('TotScore') ?></a></th> <th class="colAlarmFrames px-1"><a href="<?php echo sortHeader('AlarmFrames') ?>"><?php echo translate('AlarmBrFrames') ?><?php echo sortTag('AlarmFrames') ?></a></th>
<th class="colAvgScore"><a href="<?php echo sortHeader('AvgScore') ?>"><?php echo translate('AvgBrScore') ?><?php echo sortTag('AvgScore') ?></a></th> <th class="colTotScore px-1"><a href="<?php echo sortHeader('TotScore') ?>"><?php echo translate('TotalBrScore') ?><?php echo sortTag('TotScore') ?></a></th>
<th class="colMaxScore"><a href="<?php echo sortHeader('MaxScore') ?>"><?php echo translate('MaxBrScore') ?><?php echo sortTag('MaxScore') ?></a></th> <th class="colAvgScore px-1"><a href="<?php echo sortHeader('AvgScore') ?>"><?php echo translate('AvgBrScore') ?><?php echo sortTag('AvgScore') ?></a></th>
<th class="colMaxScore px-1"><a href="<?php echo sortHeader('MaxScore') ?>"><?php echo translate('MaxBrScore') ?><?php echo sortTag('MaxScore') ?></a></th>
<?php <?php
if ( count($storage_areas) > 1 ) { if ( count($storage_areas) > 1 ) {
?> ?>
<th class="colStorage"><?php echo translate('Storage') ?></th> <th class="colStorage px-1"><?php echo translate('Storage') ?></th>
<?php <?php
} }
if ( ZM_WEB_EVENT_DISK_SPACE ) { if ( ZM_WEB_EVENT_DISK_SPACE ) {
?> ?>
<th class="colDiskSpace"><a href="<?php echo sortHeader('DiskSpace') ?>"><?php echo translate('DiskSpace') ?><?php echo sortTag('DiskSpace') ?></a></th> <th class="colDiskSpace px-1"><a href="<?php echo sortHeader('DiskSpace') ?>"><?php echo translate('DiskSpace') ?><?php echo sortTag('DiskSpace') ?></a></th>
<?php <?php
} }
if ( ZM_WEB_LIST_THUMBS ) { if ( ZM_WEB_LIST_THUMBS ) {
?> ?>
<th class="colThumbnail"><?php echo translate('Thumbnail') ?></th> <th class="colThumbnail px-1"><?php echo translate('Thumbnail') ?></th>
<?php <?php
} }
?> ?>
<th class="colMark"><input type="checkbox" name="toggleCheck" value="1" data-checkbox-name="eids[]" data-on-click-this="updateFormCheckboxesByName"/></th> <th class="colMark px-1"><input type="checkbox" name="toggleCheck" value="1" data-checkbox-name="eids[]" data-on-click-this="updateFormCheckboxesByName"/></th>
</tr> </tr>
<?php <?php
} }
@ -192,14 +193,14 @@ while ( $event_row = dbFetchNext($results) ) {
?> ?>
<tr<?php if ($event->Archived()) echo ' class="archived"' ?>> <tr<?php if ($event->Archived()) echo ' class="archived"' ?>>
<td class="colId"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$event->Id().($event->Archived()?'*':'') ?></a></td> <td class="colId"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.$event->Id().($event->Archived()?'*':'') ?></a></td>
<td class="colName"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a><br/> <td class="colName px-1"><a href="?view=event&amp;eid=<?php echo $event->Id().$filterQuery.$sortQuery.'&amp;page=1">'.validHtmlStr($event->Name()).($event->Archived()?'*':'') ?></a><br/>
<?php <?php
if ( $event->Emailed() ) if ( $event->Emailed() )
echo 'Emailed '; echo 'Emailed ';
?> ?>
</td> </td>
<td class="colMonitorName"><?php echo makePopupLink( '?view=monitor&amp;mid='.$event->MonitorId(), 'zmMonitor'.$event->MonitorId(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td> <td class="colMonitorName px-1"><?php echo makePopupLink( '?view=monitor&amp;mid='.$event->MonitorId(), 'zmMonitor'.$event->MonitorId(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
<td class="colCause"><?php echo makePopupLink( '?view=eventdetail&amp;eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?> <td class="colCause px-1"><?php echo makePopupLink( '?view=eventdetail&amp;eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?>
<?php <?php
# display notes as small text # display notes as small text
if ( $event->Notes() ) { if ( $event->Notes() ) {
@ -215,26 +216,25 @@ while ( $event_row = dbFetchNext($results) ) {
} }
?> ?>
</td> </td>
<td class="colTime"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) . <td class="colTime text-wrap px-1"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td>
( $event->EndTime() ? ' until ' . strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) : '' ) ?> <td class="colTime text-wrap px-1"><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime()) ) ?></td>
</td> <td class="colDuration px-1"><?php echo gmdate("H:i:s", $event->Length() ) ?></td>
<td class="colDuration"><?php echo gmdate("H:i:s", $event->Length() ) ?></td> <td class="colFrames px-1"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
<td class="colFrames"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'), ( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->Frames() ) ?></td> $event->Frames() ) ?></td>
<td class="colAlarmFrames"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames', <td class="colAlarmFrames px-1"><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'), ( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->AlarmFrames() ) ?></td> $event->AlarmFrames() ) ?></td>
<td class="colTotScore"><?php echo $event->TotScore() ?></td> <td class="colTotScore px-1"><?php echo $event->TotScore() ?></td>
<td class="colAvgScore"><?php echo $event->AvgScore() ?></td> <td class="colAvgScore px-1"><?php echo $event->AvgScore() ?></td>
<td class="colMaxScore"><?php echo makePopupLink( <td class="colMaxScore px-1"><?php echo makePopupLink(
'?view=frame&amp;eid='.$event->Id().'&amp;fid=0', 'zmImage', '?view=frame&amp;eid='.$event->Id().'&amp;fid=0', 'zmImage',
array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)), $event->MaxScore() array('image', reScale($event->Width(), $scale), reScale($event->Height(), $scale)), $event->MaxScore()
); ?></td> ); ?></td>
<?php <?php
if ( count($storage_areas) > 1 ) { if ( count($storage_areas) > 1 ) {
?> ?>
<td class="colStorage"> <td class="colStorage px-1">
<?php <?php
if ( $event->StorageId() ) { if ( $event->StorageId() ) {
echo isset($StorageById[$event->StorageId()]) ? $StorageById[$event->StorageId()]->Name() : 'Unknown Storage Id: '.$event->StorageId(); echo isset($StorageById[$event->StorageId()]) ? $StorageById[$event->StorageId()]->Name() : 'Unknown Storage Id: '.$event->StorageId();
@ -252,11 +252,11 @@ while ( $event_row = dbFetchNext($results) ) {
if ( ZM_WEB_EVENT_DISK_SPACE ) { if ( ZM_WEB_EVENT_DISK_SPACE ) {
$disk_space_total += $event->DiskSpace(); $disk_space_total += $event->DiskSpace();
?> ?>
<td class="colDiskSpace"><?php echo human_filesize($event->DiskSpace()) ?></td> <td class="colDiskSpace px-1"><?php echo human_filesize($event->DiskSpace()) ?></td>
<?php <?php
} }
if ( ZM_WEB_LIST_THUMBS ) { if ( ZM_WEB_LIST_THUMBS ) {
echo '<td class="colThumbnail">'; echo '<td class="colThumbnail px-1">';
$imgSrc = $event->getThumbnailSrc(array(),'&amp;'); $imgSrc = $event->getThumbnailSrc(array(),'&amp;');
$streamSrc = $event->getStreamSrc(array( $streamSrc = $event->getStreamSrc(array(
'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&amp;'); 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single', 'rate'=>'400'), '&amp;');
@ -266,7 +266,7 @@ while ( $event_row = dbFetchNext($results) ) {
echo '</td>'; echo '</td>';
} // end if ZM_WEB_LIST_THUMBS } // end if ZM_WEB_LIST_THUMBS
?> ?>
<td class="colMark"><input type="checkbox" name="eids[]" value="<?php echo $event->Id() ?>"/></td> <td class="colMark px-1"><input type="checkbox" name="eids[]" value="<?php echo $event->Id() ?>"/></td>
</tr> </tr>
<?php <?php
} }

View File

@ -174,7 +174,7 @@ xhtmlHeaders(__FILE__, translate('EventFilter'));
<input type="hidden" name="view" value="filter"/> <input type="hidden" name="view" value="filter"/>
<hr/> <hr/>
<div id="filterSelector"><label for="<?php echo 'Id' ?>"><?php echo translate('UseFilter') ?></label> <div id="filterSelector"><label for="<?php echo 'Id' ?>"><?php echo translate('UseFilter') ?></label>
<?php <?php
if ( count($filterNames) > 1 ) { if ( count($filterNames) > 1 ) {
echo htmlSelect('Id', $filterNames, $filter->Id(), array('data-on-change-this'=>'selectFilter')); echo htmlSelect('Id', $filterNames, $filter->Id(), array('data-on-change-this'=>'selectFilter'));
} else { } else {
@ -194,16 +194,16 @@ if ( (null !== $filter->Concurrent()) and $filter->Concurrent() )
<input type="hidden" name="object" value="filter"/> <input type="hidden" name="object" value="filter"/>
<hr/> <hr/>
<?php if ( $filter->Id() ) { ?> <?php if ( $filter->Id() ) { ?>
<p class="Id"><label><?php echo translate('Id') ?></label><?php echo $filter->Id() ?></p> <p class="Id"><label><?php echo translate('Id') ?></label><?php echo $filter->Id() ?></p>
<?php } ?> <?php } ?>
<p class="Name"> <p class="Name">
<label for="filter[Name]"><?php echo translate('Name') ?></label> <label for="filter[Name]"><?php echo translate('Name') ?></label>
<input type="text" id="filter[Name]" name="filter[Name]" value="<?php echo validHtmlStr($filter->Name()) ?>" data-on-input-this="updateButtons"/> <input type="text" id="filter[Name]" name="filter[Name]" value="<?php echo validHtmlStr($filter->Name()) ?>" data-on-input-this="updateButtons"/>
</p> </p>
<?php if ( ZM_OPT_USE_AUTH ) { ?> <?php if ( ZM_OPT_USE_AUTH ) { ?>
<p><label><?php echo translate('FilterUser') ?></label> <p><label><?php echo translate('FilterUser') ?></label>
<?php <?php
global $user; global $user;
echo htmlSelect('filter[UserId]', echo htmlSelect('filter[UserId]',
ZM\User::Indexed_By_Id(), ZM\User::Indexed_By_Id(),

View File

@ -1,3 +1,9 @@
<?php
global $monIdx;
global $nextMid;
global $options;
global $monitors;
?>
var monIdx = '<?php echo $monIdx; ?>'; var monIdx = '<?php echo $monIdx; ?>';
var nextMid = "<?php echo isset($nextMid)?$nextMid:'' ?>"; var nextMid = "<?php echo isset($nextMid)?$nextMid:'' ?>";
var mode = "<?php echo $options['mode'] ?>"; var mode = "<?php echo $options['mode'] ?>";

View File

@ -1,3 +1,15 @@
<?php
global $connkey;
global $Event;
global $Monitor;
global $FilterQuery;
global $sortQuery;
global $rates;
global $rate;
global $scale;
global $streamMode;
global $popup;
?>
// //
// Import constants // Import constants
// //

View File

@ -1,3 +1,16 @@
<?php
global $filterQuery;
global $sortQuery;
global $conjunctionTypes;
global $opTypes;
global $archiveTypes;
global $weekdays;
global $states;
global $servers;
global $storageareas;
global $monitors;
global $zones;
?>
var filterQuery = '<?php echo isset($filterQuery) ? validJsStr(htmlspecialchars_decode($filterQuery)) : '' ?>'; var filterQuery = '<?php echo isset($filterQuery) ? validJsStr(htmlspecialchars_decode($filterQuery)) : '' ?>';
var sortQuery = '<?php echo isset($sortQuery) ? validJsStr(htmlspecialchars_decode($sortQuery)) : '' ?>'; var sortQuery = '<?php echo isset($sortQuery) ? validJsStr(htmlspecialchars_decode($sortQuery)) : '' ?>';

View File

@ -1,5 +1,5 @@
window.addEventListener( 'DOMContentLoaded', function() { window.addEventListener( 'DOMContentLoaded', function() {
if ( failed == true ) { if ( failed == true ) {
$('loginError').removeClass( 'hidden' ); $j('#loginError').show();
} }
} ); } );

View File

@ -157,6 +157,7 @@ function updateMethods(element) {
switch ( element.value ) { switch ( element.value ) {
case 'http' : case 'http' :
<?php <?php
global $httpMethods;
foreach( $httpMethods as $value=>$label ) { foreach( $httpMethods as $value=>$label ) {
?> ?>
methodSelector.options[methodSelector.options.length] = new Option("<?php echo htmlspecialchars($label) ?>", "<?php echo $value ?>"); methodSelector.options[methodSelector.options.length] = new Option("<?php echo htmlspecialchars($label) ?>", "<?php echo $value ?>");
@ -168,6 +169,7 @@ function updateMethods(element) {
break; break;
case 'rtsp' : case 'rtsp' :
<?php <?php
global $rtspMethods;
foreach( $rtspMethods as $value=>$label ) { foreach( $rtspMethods as $value=>$label ) {
?> ?>
methodSelector.options[methodSelector.options.length] = new Option( "<?php echo htmlspecialchars($label) ?>", "<?php echo $value ?>" ); methodSelector.options[methodSelector.options.length] = new Option( "<?php echo htmlspecialchars($label) ?>", "<?php echo $value ?>" );

View File

@ -297,8 +297,8 @@ function changeSize() {
console.log("Error finding frame for " + monitor.id); console.log("Error finding frame for " + monitor.id);
continue; continue;
} }
monitor_frame.css('width', ( width ? width+'px' : 'auto') ); monitor_frame.css('width', ( width ? width+'px' : 'auto'));
monitor_frame.css('height', ( height ? height+'px' : 'auto') ); monitor_frame.css('height', ( height ? height+'px' : 'auto'));
/*Stream could be an applet so can't use moo tools*/ /*Stream could be an applet so can't use moo tools*/
var streamImg = $('liveStream'+monitor.id); var streamImg = $('liveStream'+monitor.id);

View File

@ -28,6 +28,7 @@ var canStreamNative = <?php echo canStreamNative()?'true':'false' ?>;
var monitorData = new Array(); var monitorData = new Array();
<?php <?php
global $monitors;
foreach ( $monitors as $monitor ) { foreach ( $monitors as $monitor ) {
?> ?>
monitorData[monitorData.length] = { monitorData[monitorData.length] = {
@ -46,6 +47,7 @@ monitorData[monitorData.length] = {
layouts = new Array(); layouts = new Array();
layouts[0] = {}; // reserved, should hold which fields to clear when transitioning layouts[0] = {}; // reserved, should hold which fields to clear when transitioning
<?php <?php
global $layouts;
foreach ( $layouts as $layout ) { foreach ( $layouts as $layout ) {
?> ?>
layouts[<?php echo $layout->Id() ?>] = {"Name":"<?php echo $layout->Name()?>","Positions":<?php echo $layout->Positions() ?>}; layouts[<?php echo $layout->Id() ?>] = {"Name":"<?php echo $layout->Name()?>","Positions":<?php echo $layout->Positions() ?>};

View File

@ -4,6 +4,20 @@ $TimeZone = new DateTimeZone( ini_get('date.timezone') );
$now = new DateTime('now', $TimeZone); $now = new DateTime('now', $TimeZone);
$offset = $TimeZone->getOffset($now); $offset = $TimeZone->getOffset($now);
echo $offset.'; // '.floor($offset / 3600).' hours '; echo $offset.'; // '.floor($offset / 3600).' hours ';
global $defaultScale;
global $liveMode;
global $fitMode;
global $speeds;
global $speedIndex;
global $initialDisplayInterval;
global $minTimeSecs;
global $maxTimeSecs;
global $minTime;
global $maxTime;
global $monitors;
global $eventsSql;
global $framesSql;
?> ?>
var currentScale=<?php echo $defaultScale?>; var currentScale=<?php echo $defaultScale?>;
@ -40,7 +54,7 @@ $maxScore = 0;
if ( !$liveMode ) { if ( !$liveMode ) {
$result = dbQuery($eventsSql); $result = dbQuery($eventsSql);
if ( !$result ) { if ( !$result ) {
Fatal('SQL-ERR'); ZM\Fatal('SQL-ERR');
return; return;
} }
@ -146,7 +160,6 @@ foreach ( ZM\Server::find() as $Server ) {
echo 'Servers[' . $Server->Id() . '] = new Server(' . $Server->to_json(). ");\n"; echo 'Servers[' . $Server->Id() . '] = new Server(' . $Server->to_json(). ");\n";
} }
echo ' echo '
var monitorName = []; var monitorName = [];
var monitorLoading = []; var monitorLoading = [];
@ -167,8 +180,8 @@ var monitorCanvasCtx = [];
var monitorPtr = []; // monitorName[monitorPtr[0]] is first monitor var monitorPtr = []; // monitorName[monitorPtr[0]] is first monitor
'; ';
$numMonitors=0; // this array is indexed by the monitor ID for faster access later, so it may be sparse $numMonitors = 0; // this array is indexed by the monitor ID for faster access later, so it may be sparse
$avgArea=floatval(0); // Calculations the normalizing scale $avgArea = floatval(0); // Calculations the normalizing scale
foreach ( $monitors as $m ) { foreach ( $monitors as $m ) {
$avgArea = $avgArea + floatval($m->Width() * $m->Height()); $avgArea = $avgArea + floatval($m->Width() * $m->Height());

View File

@ -6,13 +6,14 @@
// will save the GET request via the postLoginQuery variable. After logging in, this // will save the GET request via the postLoginQuery variable. After logging in, this
// view receives the postLoginQuery via the login form submission, and we can then // view receives the postLoginQuery via the login form submission, and we can then
// redirect the user to his original intended destination by appending it to the URL. // redirect the user to his original intended destination by appending it to the URL.
//
?> ?>
( $j(
function () { function () {
// Append '?(GET query)' to URL if the GET query is not empty. // Append '?(GET query)' to URL if the GET query is not empty.
var querySuffix = '<?php var querySuffix = '<?php
if (!empty($_SESSION['postLoginQuery'])) { if ( !empty($_SESSION['postLoginQuery']) ) {
parse_str($_SESSION['postLoginQuery'], $queryParams); parse_str($_SESSION['postLoginQuery'], $queryParams);
echo '?' . http_build_query($queryParams); echo '?' . http_build_query($queryParams);
zm_session_start(); zm_session_start();

View File

@ -1,3 +1,12 @@
<?php
global $filterQuery;
global $monitors;
global $minTime;
global $midTime;
global $maxTime;
global $range;
global $majXScale;
?>
var filterQuery = '<?php echo validJsStr($filterQuery) ?>'; var filterQuery = '<?php echo validJsStr($filterQuery) ?>';
<?php <?php

View File

@ -1,3 +1,10 @@
<?php
global $streamMode;
global $showPtzControls;
global $connkey;
global $monitor;
global $scale;
?>
// //
// Import constants // Import constants
// //

View File

@ -178,14 +178,19 @@ function applyPreset() {
function toPixels(field, maxValue) { function toPixels(field, maxValue) {
if ( field.value != '' ) { if ( field.value != '' ) {
field.value = Math.round((field.value*maxValue)/100); field.value = Math.round((field.value*maxValue)/100);
if ( field.value > maxValue ) field.value = maxValue;
} }
field.setAttribute('step', 1); field.setAttribute('step', 1);
field.setAttribute('max', monitorArea); field.setAttribute('max', maxValue);
} }
// maxValue is the max Pixels value which is normally the max area
function toPercent(field, maxValue) { function toPercent(field, maxValue) {
if ( field.value != '' ) { if ( field.value != '' ) {
field.value = Math.round((100*100*field.value)/maxValue)/100; field.value = Math.round((100*100*field.value)/maxValue)/100;
if ( field.value > 100 ) {
field.value = 100;
}
} }
field.setAttribute('step', 0.01); field.setAttribute('step', 0.01);
field.setAttribute('max', 100); field.setAttribute('max', 100);
@ -312,9 +317,7 @@ function updateActivePoint(index) {
$('newZone[Points]['+index+'][y]').value = y; $('newZone[Points]['+index+'][y]').value = y;
zone['Points'][index].x = x; zone['Points'][index].x = x;
zone['Points'][index].y = y; zone['Points'][index].y = y;
console.log('hello');
var Point = $('zonePoly').points.getItem(index); var Point = $('zonePoly').points.getItem(index);
console.log('hello');
Point.x = x; Point.x = x;
Point.y = y; Point.y = y;
updateArea(); updateArea();
@ -450,6 +453,7 @@ function drawZonePoints() {
'name': 'newZone[Points]['+i+'][x]', 'name': 'newZone[Points]['+i+'][x]',
'value': zone['Points'][i].x, 'value': zone['Points'][i].x,
'type': 'number', 'type': 'number',
'class': 'ZonePoint',
'min': '0', 'min': '0',
'max': maxX, 'max': maxX,
'data-point-index': i 'data-point-index': i
@ -464,6 +468,7 @@ function drawZonePoints() {
'name': 'newZone[Points]['+i+'][y]', 'name': 'newZone[Points]['+i+'][y]',
'value': zone['Points'][i].y, 'value': zone['Points'][i].y,
'type': 'number', 'type': 'number',
'class': 'ZonePoint',
'min': '0', 'min': '0',
'max': maxY, 'max': maxY,
'data-point-index': i 'data-point-index': i
@ -676,7 +681,6 @@ var watchdogFunctions = {
//Make sure the various refreshes are still taking effect //Make sure the various refreshes are still taking effect
function watchdogCheck(type) { function watchdogCheck(type) {
if ( watchdogInactive[type] ) { if ( watchdogInactive[type] ) {
console.log("Detected streamWatch of type: " + type + " stopped, restarting");
watchdogFunctions[type](); watchdogFunctions[type]();
watchdogInactive[type] = false; watchdogInactive[type] = false;
} else { } else {

View File

@ -1,3 +1,14 @@
<?php
global $presets;
global $zone;
global $newZone;
global $monitor;
global $selfIntersecting;
global $streamMode;
global $connkey;
global $streamSrc;
?>
var presets = new Object(); var presets = new Object();
<?php <?php
foreach ( $presets as $preset ) { foreach ( $presets as $preset ) {
@ -21,7 +32,7 @@ presets[<?php echo $preset['Id'] ?>] = {
'ExtendAlarmFrames': '<?php echo $preset['ExtendAlarmFrames'] ?>' 'ExtendAlarmFrames': '<?php echo $preset['ExtendAlarmFrames'] ?>'
}; };
<?php <?php
} } # end foreach preset
?> ?>
var zone = { var zone = {

View File

@ -1,3 +1,7 @@
<?php
global $connkey;
global $monitor;
?>
var connKey = '<?php echo $connkey ?>'; var connKey = '<?php echo $connkey ?>';
var monitorUrl = '<?php echo ( $monitor->UrlToIndex() ) ?>'; var monitorUrl = '<?php echo ( $monitor->UrlToIndex() ) ?>';
var CMD_QUIT = <?php echo CMD_QUIT ?>; var CMD_QUIT = <?php echo CMD_QUIT ?>;

View File

@ -25,94 +25,83 @@ if ( !canView('System') ) {
$focusWindow = true; $focusWindow = true;
xhtmlHeaders(__FILE__, translate('SystemLog') ); xhtmlHeaders(__FILE__, translate('SystemLog'));
?> ?>
<body> <body>
<div id="page"> <div id="page">
<div id="header"> <div id="header">
<table class="table"> <div id="logSummary" class="text-center">
<tr class="row"> <?php echo translate('State') ?>: <span id="logState"></span>/
<td class="col text-center"> <?php echo translate('Total') ?>: <span id="totalLogs"></span>/
<div id="logSummary"> <?php echo translate('Available') ?>: <span id="availLogs"></span>/
<?php echo translate('State') ?>: <span id="logState"></span>/ <?php echo translate('Displaying') ?>: <span id="displayLogs"></span>/
<?php echo translate('Total') ?>: <span id="totalLogs"></span>/ <?php echo translate('Updated') ?>: <span id="lastUpdate"></span>
<?php echo translate('Available') ?>: <span id="availLogs"></span>/
<?php echo translate('Displaying') ?>: <span id="displayLogs"></span>/
<?php echo translate('Updated') ?>: <span id="lastUpdate"></span>
</div>
</td>
</tr>
<tr class="row">
<td class="col text-center">
<div class="btn-group">
<button type="button" data-on-click="expandLog"><?php echo translate('More') ?></button>
<button type="button" data-on-click="clearLog"><?php echo translate('Clear') ?></button>
<button type="button" data-on-click="refreshLog"><?php echo translate('Refresh') ?></button>
<button type="button" data-on-click="exportLog"><?php echo translate('Export') ?></button>
<button type="button" data-on-click="closeWindow"><?php echo translate('Close') ?></button>
</div> <!--btn-->
</td>
</tr>
</table>
</div> <!--header-->
<div id="content">
<form id="logForm" name="logForm" method="post" action="?">
<div id="filters">
<table class="table-condensed">
<tr class="row">
<td class="col">
<label><?php echo translate('Component') ?></label>
<select class="form-control chosen" id="filter[Component]" data-on-change="filterLog"><option value="">-----</option></select>
</td>
<td class="col">
<label><?php echo translate('Server') ?></label>
<select class="form-control chosen" id="filter[ServerId]" data-on-change="filterLog"><option value="">-----</option></select>
</td>
<td class="col">
<label><?php echo translate('Pid') ?></label>
<select class="form-control chosen" id="filter[Pid]" data-on-change="filterLog"><option value="">-----</option></select>
</td>
</tr>
<tr class="row">
<td class="col">
<label><?php echo translate('Level') ?></label>
<select class="form-control chosen" id="filter[Level]" data-on-change="filterLog"><option value="">---</option></select>
</td>
<td class="col">
<label><?php echo translate('File') ?></label>
<select class="form-control chosen" id="filter[File]" data-on-change="filterLog"><option value="">------</option></select>
</td>
<td class="col">
<label><?php echo translate('Line') ?></label>
<select class="form-control chosen" id="filter[Line]" data-on-change="filterLog"><option value="">----</option></select>
</td>
</tr>
</table>
<button type="reset" data-on-click="resetLog"><?php echo translate('Reset') ?></button>
</div>
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<table id="logTable" class="major">
<thead class="thead-highlight">
<tr>
<th><?php echo translate('DateTime') ?></th>
<th class="table-th-nosort"><?php echo translate('Component') ?></th>
<th class="table-th-nosort"><?php echo translate('Server') ?></th>
<th class="table-th-nosort"><?php echo translate('Pid') ?></th>
<th class="table-th-nosort"><?php echo translate('Level') ?></th>
<th class="table-th-nosort"><?php echo translate('Message') ?></th>
<th class="table-th-nosort"><?php echo translate('File') ?></th>
<th class="table-th-nosort"><?php echo translate('Line') ?></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div id="contentButtons">
</div> </div>
</form> <div class="btn-toolbar text-center">
</div> <div class="btn-group">
<button type="button" data-on-click="expandLog"><?php echo translate('More') ?></button>
<button type="button" data-on-click="clearLog"><?php echo translate('Clear') ?></button>
<button type="button" data-on-click="refreshLog"><?php echo translate('Refresh') ?></button>
<button type="button" data-on-click="exportLog"><?php echo translate('Export') ?></button>
<button type="reset" data-on-click="resetLog"><?php echo translate('Reset') ?></button>
</div> </div>
<div class="btn-group pull-right">
<button type="button" data-on-click="closeWindow"><?php echo translate('Close') ?></button>
</div>
</div> <!--btn-->
</div> <!--header-->
<div id="content">
<form id="logForm" name="logForm" method="post" action="?">
<div class="container" id="filters">
<div class="row">
<div class="col">
<label><?php echo translate('Component') ?></label>
<select class="form-control chosen" id="filter[Component]" data-on-change="filterLog"><option value="">-----</option></select>
</div>
<div class="col">
<label><?php echo translate('Server') ?></label>
<select class="form-control chosen" id="filter[ServerId]" data-on-change="filterLog"><option value="">-----</option></select>
</div>
<div class="col">
<label><?php echo translate('Pid') ?></label>
<select class="form-control chosen" id="filter[Pid]" data-on-change="filterLog"><option value="">-----</option></select>
</div>
<div class="col">
<label><?php echo translate('Level') ?></label>
<select class="form-control chosen" id="filter[Level]" data-on-change="filterLog"><option value="">---</option></select>
</div>
<div class="col">
<label><?php echo translate('File') ?></label>
<select class="form-control chosen" id="filter[File]" data-on-change="filterLog"><option value="">------</option></select>
</div>
<div class="col">
<label><?php echo translate('Line') ?></label>
<select class="form-control chosen" id="filter[Line]" data-on-change="filterLog"><option value="">----</option></select>
</div>
</div><!--row-->
</div><!--container-->
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<table id="logTable" class="major">
<thead class="thead-highlight">
<tr>
<th><?php echo translate('DateTime') ?></th>
<th class="table-th-nosort"><?php echo translate('Component') ?></th>
<th class="table-th-nosort"><?php echo translate('Server') ?></th>
<th class="table-th-nosort"><?php echo translate('Pid') ?></th>
<th class="table-th-nosort"><?php echo translate('Level') ?></th>
<th class="table-th-nosort"><?php echo translate('Message') ?></th>
<th class="table-th-nosort"><?php echo translate('File') ?></th>
<th class="table-th-nosort"><?php echo translate('Line') ?></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div id="contentButtons">
</div>
</div><!--content-->
</form>
</div><!--page-->
<div id="exportLog" class="overlay"> <div id="exportLog" class="overlay">
<div class="overlayHeader"> <div class="overlayHeader">
<div class="overlayTitle"><?php echo translate('ExportLog') ?></div> <div class="overlayTitle"><?php echo translate('ExportLog') ?></div>
@ -142,8 +131,8 @@ xhtmlHeaders(__FILE__, translate('SystemLog') );
<button type="button" id="exportButton" value="Export" data-on-click="exportRequest"><?php echo translate('Export') ?></button> <button type="button" id="exportButton" value="Export" data-on-click="exportRequest"><?php echo translate('Export') ?></button>
<button type="button" value="Cancel" class="overlayCloser"><?php echo translate('Cancel') ?></button> <button type="button" value="Cancel" class="overlayCloser"><?php echo translate('Cancel') ?></button>
</form> </form>
</div> </div><!--overlayContent-->
</div> </div><!--overlaybody-->
</div> </div><!-- exportLog-->
</body> </body>
</html> </html>

View File

@ -1060,8 +1060,11 @@ include('_monitor_source_nvsocket.php');
?> ?>
</td></tr> </td></tr>
<tr> <tr>
<td><?php echo translate('OptionalEncoderParam') ?></td> <td><?php echo translate('OptionalEncoderParam') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_ENCODER_PARAMETERS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
<td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($monitor->EncoderParameters()) ?></textarea></td></tr> <td>
<textarea name="newMonitor[EncoderParameters]" rows="<?php echo count(explode("\n", $monitor->EncoderParameters())); ?>"><?php echo validHtmlStr($monitor->EncoderParameters()) ?></textarea>
</td>
</tr>
<tr><td><?php echo translate('RecordAudio') ?></td><td> <tr><td><?php echo translate('RecordAudio') ?></td><td>
<?php if ( $monitor->Type() == 'Ffmpeg' ) { ?> <?php if ( $monitor->Type() == 'Ffmpeg' ) { ?>
<input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/> <input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/>

View File

@ -56,10 +56,10 @@ xhtmlHeaders(__FILE__, translate('Options'));
?> ?>
<body> <body>
<?php echo getNavBarHTML(); ?> <?php echo getNavBarHTML(); ?>
<div class="container-fluid"> <div class="container-fluid h-100">
<div class="row flex-nowrap"> <div class="row flex-nowrap h-100">
<nav id="sidebar"> <nav id="sidebar h-100">
<ul class="nav nav-pills flex-column"> <ul class="nav nav-pills flex-column h-100">
<?php <?php
foreach ( $tabs as $name=>$value ) { foreach ( $tabs as $name=>$value ) {
?> ?>
@ -69,7 +69,7 @@ foreach ( $tabs as $name=>$value ) {
?> ?>
</ul> </ul>
</nav> </nav>
<div class="col-sm-10 col-sm-offset-2"> <div class="container-fluid col-sm-offset-2 h-100 pr-0">
<br/> <br/>
<div id="options"> <div id="options">
<?php <?php
@ -440,8 +440,8 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
$optionPromptText = !empty($OLANG[$shortName])?$OLANG[$shortName]['Prompt']:$value['Prompt']; $optionPromptText = !empty($OLANG[$shortName])?$OLANG[$shortName]['Prompt']:$value['Prompt'];
?> ?>
<div class="form-group form-row"> <div class="form-group form-row">
<label for="<?php echo $name ?>" class="col-sm-3 control-label form-control-sm font-weight-bold text-right"><?php echo $shortName ?></label> <label for="<?php echo $name ?>" class="col-md-4 control-label text-md-right"><?php echo $shortName ?></label>
<div class="col-sm-6"> <div class="col-md">
<?php <?php
if ( $value['Type'] == 'boolean' ) { if ( $value['Type'] == 'boolean' ) {
?> ?>
@ -456,7 +456,7 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
$options = explode('|', $value['Hint']); $options = explode('|', $value['Hint']);
if ( count($options) > 3 ) { if ( count($options) > 3 ) {
?> ?>
<select class="form-control form-control-sm" name="newConfig[<?php echo $name ?>]"<?php echo $canEdit?'':' disabled="disabled"' ?>> <select class="form-control-sm" name="newConfig[<?php echo $name ?>]"<?php echo $canEdit?'':' disabled="disabled"' ?>>
<?php <?php
foreach ( $options as $option ) { foreach ( $options as $option ) {
if ( preg_match('/^([^=]+)=(.+)$/', $option, $matches) ) { if ( preg_match('/^([^=]+)=(.+)$/', $option, $matches) ) {
@ -496,19 +496,19 @@ foreach ( array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)) as
<?php <?php
} else if ( $value['Type'] == 'integer' ) { } else if ( $value['Type'] == 'integer' ) {
?> ?>
<input type="number" class="form-control form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/> <input type="number" class="form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/>
<?php <?php
} else if ( $value['Type'] == 'hexadecimal' ) { } else if ( $value['Type'] == 'hexadecimal' ) {
?> ?>
<input type="text" class="form-control form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/> <input type="text" class="form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/>
<?php <?php
} else if ( $value['Type'] == 'decimal' ) { } else if ( $value['Type'] == 'decimal' ) {
?> ?>
<input type="text" class="form-control form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/> <input type="text" class="form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/>
<?php <?php
} else { } else {
?> ?>
<input type="text" class="form-control form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/> <input type="text" class="form-control-sm" id="<?php echo $name ?>" name="newConfig[<?php echo $name ?>]" value="<?php echo validHtmlStr($value['Value']) ?>" <?php echo $canEdit?'':' disabled="disabled"' ?>/>
<?php <?php
} }
?> ?>

View File

@ -28,10 +28,10 @@ $zmuCommand = getZmuCommand(' -m '.escapeshellarg($_REQUEST['mid']).' -B -C -H -
$zmuOutput = exec( $zmuCommand ); $zmuOutput = exec( $zmuCommand );
list($brightness, $contrast, $hue, $colour) = explode(' ', $zmuOutput); list($brightness, $contrast, $hue, $colour) = explode(' ', $zmuOutput);
$monitor->Brightness() = $brightness; $monitor->Brightness($brightness);
$monitor->Contrast() = $contrast; $monitor->Contrast($contrast);
$monitor->Hue() = $hue; $monitor->Hue($hue);
$monitor->Colour() = $colour; $monitor->Colour($colour);
$focusWindow = true; $focusWindow = true;

View File

@ -33,15 +33,23 @@ xhtmlHeaders(__FILE__, translate('Shutdown').' '.translate('Restart'));
<h2><?php echo translate('Shutdown').' '.translate('Restart') ?></h2> <h2><?php echo translate('Shutdown').' '.translate('Restart') ?></h2>
</div> </div>
<div id="content"> <div id="content">
<?php
if ( !defined('ZM_PATH_SHUTDOWN') or ZM_PATH_SHUTDOWN == '' ) {
echo '<div class="error">ZM_PATH_SHUTDOWN is not defined. This is normally configured in /etc/zm/conf.d/01-system-paths.conf</div>';
} else if ( !file_exists(ZM_PATH_SHUTDOWN) ) {
echo '<div class="error">Path does not exist for ZM_PATH_SHUTDOWN. Current value is '.ZM_PATH_SHUTDOWN.'</div>';
} else {
?>
<form name="contentForm" id="contentForm" method="post" action="?"> <form name="contentForm" id="contentForm" method="post" action="?">
<input type="hidden" name="view" value="shutdown"/> <input type="hidden" name="view" value="shutdown"/>
<?php <?php
if ( isset($output) ) { if ( isset($output) ) {
echo '<p>'.implode('<br/>', $output).'</p>'; echo '<p>'.implode('<br/>', $output).'</p>';
} }
if ( isset($_POST['when']) and ($_POST['when'] != 'NOW') and ($action != 'cancel') ) { if ( isset($_POST['when']) and ($_POST['when'] != 'NOW') and ($action != 'cancel') ) {
echo '<p>You may cancel this shutdown by clicking '.translate('Cancel').'</p>'; echo '<p>You may cancel this shutdown by clicking '.translate('Cancel').'</p>';
} }
?> ?>
<p class="warning"><h2>Warning</h2> <p class="warning"><h2>Warning</h2>
This command will either shutdown or restart all ZoneMinder Servers<br/> This command will either shutdown or restart all ZoneMinder Servers<br/>
@ -52,17 +60,20 @@ xhtmlHeaders(__FILE__, translate('Shutdown').' '.translate('Restart'));
</p> </p>
<div id="contentButtons"> <div id="contentButtons">
<?php <?php
if ( isset($_POST['when']) and ($_POST['when'] != 'NOW') and ($action != 'cancel') ) { if ( isset($_POST['when']) and ($_POST['when'] != 'NOW') and ($action != 'cancel') ) {
?> ?>
<button type="submit" name="action" value="cancel"><?php echo translate('Cancel') ?></button> <button type="submit" name="action" value="cancel"><?php echo translate('Cancel') ?></button>
<?php <?php
} }
?> ?>
<button type="submit" name="action" value="restart"><?php echo translate('Restart') ?></button> <button type="submit" name="action" value="restart"><?php echo translate('Restart') ?></button>
<button type="submit" name="action" value="shutdown"><?php echo translate('Shutdown') ?></button> <button type="submit" name="action" value="shutdown"><?php echo translate('Shutdown') ?></button>
<button type="button" data-on-click="closeWindow"><?php echo translate('Close') ?></button> <button type="button" data-on-click="closeWindow"><?php echo translate('Close') ?></button>
</div> </div>
</form> </form>
<?php
} # end if PATH_SHUTDOWN looks value
?>
</div> </div>
</div> </div>
</body> </body>

View File

@ -17,70 +17,68 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
global $running;
if ( !canEdit('System') ) { if ( !canEdit('System') ) {
$view = 'error'; $view = 'error';
return; return;
} }
?>
<div id="modalState" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="ModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header"> $content = '';
<button type="button" class="btn" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h5 class="modal-title w-100 text-center" id="ModalCenterTitle"><?php echo translate('RunState') ?></h5>
</div>
<div class="modal-body">
<form class="" name="contentForm" method="get" action="?view=state">
<input type="hidden" name="view" value="state"/>
<input type="hidden" name="action" value="state"/>
<input type="hidden" name="apply" value="1"/>
<div class="form-group">
<label for="runState" class="col-md-3 col-form-label float-left">Change State</label>
<div class="col-md-9">
<select id="runState" name="runState" class="form-control">
<?php
if ( $running ) { if ( $running ) {
?> $content .= '<option value="stop" selected="selected">' .translate('Stop'). '</option>'.PHP_EOL;
<option value="stop" selected="selected"><?php echo translate('Stop') ?></option> $content .= '<option value="restart">' .translate('Restart'). '</option>'.PHP_EOL;
<option value="restart"><?php echo translate('Restart') ?></option>
<?php
} else { } else {
?> $content .= '<option value="start" selected="selected">' .translate('Start'). '</option>'.PHP_EOL;
<option value="start" selected="selected"><?php echo translate('Start') ?></option>
<?php
} }
$states = dbFetchAll('SELECT * FROM States'); $states = dbFetchAll('SELECT * FROM States');
foreach ( $states as $state ) { foreach ( $states as $state ) {
?> $selected = $state['IsActive'] ? 'selected="selected"' : '';
<option value="<?php echo validHtmlStr($state['Name']) ?>" <?php echo $state['IsActive'] ? 'selected="selected"' : '' ?>>
<?php echo validHtmlStr($state['Name']); ?> $content .= '<option value="' .validHtmlStr($state["Name"]). '" ' .$selected. '>'.PHP_EOL;
</option> $content .= validHtmlStr($state['Name']).PHP_EOL;
<?php $content .= '</option>'.PHP_EOL;
} }
?> ?>
</select> <div id="modalState" class="modal fade" tabindex="-1">
</div><!--col-md-9--> <div class="modal-dialog modal-dialog-centered">
</div><!--form-group--> <div class="modal-content">
<div class="form-group"> <div class="modal-header">
<label for="newState" class="col-md-3 col-form-label float-left"><?php echo translate('NewState') ?></label> <h5 class="modal-title">Run State</h5>
<div class="col-md-9"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<input class="form-control" type="text" id="newState"/> <span aria-hidden="true">&times;</span>
</div> </button>
</div> </div>
<div class="modal-body">
<form class="" name="contentForm" method="get" action="?view=state">
<input type="hidden" name="view" value="state"/>
<input type="hidden" name="action" value="state"/>
<input type="hidden" name="apply" value="1"/>
<div class="form-group">
<label for="runState" class="col-md-3 col-form-label float-left">Change State</label>
<div class="col-md-9">
<select id="runState" name="runState" class="form-control">
<?php echo $content ?>
</select>
</div><!--col-md-9-->
</div><!--form-group-->
<div class="form-group">
<label for="newState" class="col-md-3 col-form-label float-left"><?php echo translate('NewState') ?></label>
<div class="col-md-9">
<input class="form-control" type="text" id="newState"/>
</div>
</div>
</form> </form>
</div> <!-- modal-body --> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-primary" type="button" id="btnApply"><?php echo translate('Apply') ?></button> <button class="btn btn-primary" type="button" id="btnApply"><?php echo translate('Apply') ?></button>
<button class="btn btn-primary" type="button" id="btnSave" disabled><?php echo translate('Save') ?></button> <button class="btn btn-primary" type="button" id="btnSave" disabled><?php echo translate('Save') ?></button>
<button class="btn btn-danger" type="button" id="btnDelete" disabled><?php echo translate('Delete') ?></button> <button class="btn btn-danger" type="button" id="btnDelete" disabled><?php echo translate('Delete') ?></button>
<p class="pull-left hidden" id="pleasewait"><?php echo translate('PleaseWait') ?></p> <p class="pull-left hidden" id="pleasewait"><?php echo translate('PleaseWait') ?></p>
</div><!-- footer --> </div>
</div> <!-- content --> </div>
</div> <!-- dialog --> </div>
</div> <!-- state --> </div>

Some files were not shown because too many files have changed in this diff Show More