Merge branch 'master' into improve_session

This commit is contained in:
Isaac Connor 2019-02-22 09:28:01 -05:00
commit 73a0de51b6
164 changed files with 1839 additions and 1569 deletions

View File

@ -17,6 +17,7 @@ In order to submit a bug report, please populate the fields below this line. Thi
- Version of ZoneMinder [release version, development version, or commit] - Version of ZoneMinder [release version, development version, or commit]
- How you installed ZoneMinder [e.g. PPA, RPMFusion, from-source, etc] - How you installed ZoneMinder [e.g. PPA, RPMFusion, from-source, etc]
- Full name and version of OS - Full name and version of OS
- Browser name and version (if this is an issue with the web interface)
**If the issue concerns a camera** **If the issue concerns a camera**
- Make and Model - Make and Model

View File

@ -11,6 +11,7 @@ assignees: ''
- Version of ZoneMinder [release version, development version, or commit] - Version of ZoneMinder [release version, development version, or commit]
- How you installed ZoneMinder [e.g. PPA, RPMFusion, from-source, etc] - How you installed ZoneMinder [e.g. PPA, RPMFusion, from-source, etc]
- Full name and version of OS - Full name and version of OS
- Browser name and version (if this is an issue with the web interface)
**If the issue concerns a camera** **If the issue concerns a camera**
- Make and Model - Make and Model

10
AUTHORS
View File

@ -1,10 +0,0 @@
ZoneMinder - A Linux based camera monitoring and analysis tool.
This project was imagined and created by Philip Coombes in
September 2002, shortly after being burglarised of his power tools.
He can be contacted at philip.coombes@zoneminder.com
In early 2013 after nearly two years of no development,
the community reached out to Phil in an attempt to open up the
project. With Phil's blessing, the code was migrated to github,
and the community took over the project.

1
BUGS
View File

@ -1 +0,0 @@
Please see https://github.com/ZoneMinder/ZoneMinder/issues?state=open

View File

@ -1 +0,0 @@
This is too hard to maintain. See https://github.com/ZoneMinder/ZoneMinder/commits/master

147
INSTALL
View File

@ -1,147 +0,0 @@
Installing ZoneMinder with cmake
--------------------------------
Starting with ZoneMinder 1.26.4, ZoneMinder can now be installed using cmake. This requires cmake version 2.6 or newer.
cmake is an alternative to the autotools collection (libtool, autoconf, automake, autoheader and such). Its more recent and has many advantages, including, but not limited to:
* One program (cmake) instead of multiple. (libtool, autoconf, automake, etc)
* One file per directory (CMakeLists.txt) instead of multiple. (configure.ac, Makefile.am and sometimes more)
* One syntax (cmake's syntax) instead of multiple. (bash and m4)
* Generation of makefiles for many platforms, including Windows.
* Newer than autotools and is being actively developed.
* Generates colored makefiles with progress indicator.
* Slightly faster because its based on C and not bash.
* Lots of documentation, unlike autotools: http://www.cmake.org/cmake/help/cmake2.6docs.html
At this point, its still possible to use autotools for the ZoneMinder project. Choosing cmake or autotools is now a matter of preference.
Hopefully in the future, cmake will become the default way to install ZoneMinder.
Important differences
---------------------
* Unlike the autotools way, the cmake way does not require any options. It attempts to detect some things by its own (system directories, libarch, web user and group) and uses defaults for others (installation paths and such).
* Unlike the autotools way, which links the binaries to a fixed list of libraries, the cmake way only links to libraries that it found on the system. If a library is not found, but required, a fatal error will be shown during the configuration step.
* Unlike the autotools way, the cmake way does not modify the system in any way it shouldn't. It only does what its supposed to do: Install files to your system. Nothing else and nothing leaks out of the DESTDIR environment variable (if used). This means that depending on your configuration, there might be an extra required step after installation: to link WEB_PATH/events and WEB_PATH/images folders to the correct places.
Configuration
-------------
cmake by default does not require any parameters, but its possible to override the defaults with the options below.
Configuration can be done in 4 ways:
1) As a command line parameter, e.g. cmake -DCMAKE_VERBOSE_MAKEFILE=ON .
2) Using cmake-gui
3) Providing cmake with an initial cache file with the -C option
IMPORTANT: Do not use the -C option if any major part of your system, excluding the version of zoneminder, has changed.
For example, do not use this option if: you have upgraded your distro to a new version, have gone from 32 to 64 bits,
or have migrated from one machine to another.
4) By editing the cache file CMakeCache.txt (after it has been generated) - Not recommended
Possible configuration options:
ZM_RUNDIR Location of transient process files, default: /var/run/zm
ZM_SOCKDIR Location of Unix domain socket files, default /var/run/zm
ZM_TMPDIR Location of temporary files, default: /tmp/zm
ZM_LOGDIR Location of generated log files, default: /var/log/zm
ZM_WEBDIR Location of the web files, default: <prefix>/share/zoneminder/www
ZM_CGIDIR Location of the cgi-bin files, default: <prefix>/libexec/zoneminder/cgi-bin
ZM_CONTENTDIR Location of dynamic content (events and images), default: /var/lib/zoneminder
ZM_DB_HOST Hostname where ZoneMinder database located, default: localhost
ZM_DB_NAME Name of ZoneMinder database, default: zm
ZM_DB_USER Name of ZoneMinder database user, default: zmuser
ZM_DB_PASS Password of ZoneMinder database user, default: zmpass
ZM_DB_SSL_CA_CERT Path to SSL CA certificate, default: empty; SSL not enabled
ZM_DB_SSL_CLIENT_KEY Path to SSL client key, default: empty; SSL not enabled
ZM_DB_SSL_CLIENT_CERT Path to SSL client certificate, default: empty; SSL not enabled
ZM_WEB_USER The user apache or the local web server runs on. Leave empty for automatic detection. If that fails, you can use this variable to force
ZM_WEB_GROUP The group apache or the local web server runs on, Leave empty to be the same as the web user
ZM_DIR_EVENTS Location where events are recorded to, default: ZM_CONTENTDIR/events
ZM_DIR_SOUNDS Location to look for optional sound files, default: sounds
ZM_PATH_ZMS Web url to zms streaming server, default: /cgi-bin/nph-zms
Advanced:
ZM_PATH_MAP Location to save mapped memory files, default: /dev/shm
ZM_PATH_ARP Full path to compatible arp binary. Leave empty for automatic detection.
ZM_CONFIG_DIR Location of the main ZoneMinder config file, zm.conf. default: /etc/zm
ZM_CONFIG_SUBDIR Location of custom config files. default: ZM_CONFIG_DIR/conf.d
ZM_EXTRA_LIBS A list of optional libraries, separated by semicolons, e.g. ssl;theora
ZM_MYSQL_ENGINE MySQL engine to use with database, default: InnoDB
ZM_NO_MMAP Set to ON to not use mmap shared memory. Shouldn't be enabled unless you experience problems with the shared memory. default: OFF
ZM_NO_X10 Set to ON to build ZoneMinder without X10 support. default: OFF
ZM_PERL_MM_PARMS By default, ZoneMinder's Perl modules are installed into the Vendor folders, as defined by your installation of Perl. You can change that here. Consult Perl's MakeMaker documentation for a definition of acceptable parameters. If you set this to something that causes the modules to be installed outside Perl's normal serach path, then you will also need to set ZM_PERL_SEARCH_PATH accordingly. default: "INSTALLDIRS=vendor NO_PACKLIST=1 NO_PERLLOCAL=1"
ZM_PERL_SEARCH_PATH Use to add a folder to your Perl's search path. This will need to be set in cases where ZM_PERL_MM_PARMS has been modified such that ZoneMinder's Perl modules are installed outside Perl's default search path. default: ""
Useful configuration options provided by cmake:
CMAKE_VERBOSE_MAKEFILE - Set this to ON (default OFF) to see what cmake is doing. Very useful for troubleshooting.
CMAKE_BUILD_TYPE - Set this to Debug (default Release) to build ZoneMinder with debugging enabled.
CMAKE_INSTALL_PREFIX - Use this to change the prefix (default /usr/local). This option behaves like --prefix from autoconf. Package maintainers will probably want to set this to "/usr".
Useful environment variables provided by cmake:
CMAKE_INCLUDE_PATH - Use this to add to the include search path.
CMAKE_LIBRARY_PATH - Use this to add to the library search path.
CMAKE_PREFIX_PATH - Use this to add to both include and library search paths. <path>/include will be added to the include search path and <path>/lib to the library search path. Multiple paths can be specified, separated by a : character. For example: export CMAKE_PREFIX_PATH="/opt/libjpeg-turbo:/opt/ffmpeg-from-git"
CFLAGS, CPPFLAGS and other environment variables:
To append to the CFLAGS and CXXFLAGS, please use the CFLAGS and CXXFLAGS environment variables.
Or use the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS configuration options.
To replace the CFLAGS and CXXFLAGS entirely:
* For the Release build type: use CMAKE_C_FLAGS_RELEASE for the CFLAGS and CMAKE_CXX_FLAGS_RELEASE for the CXXFLAGS
* For the Debug build type: use CMAKE_C_FLAGS_DEBUG for the CFLAGS and CMAKE_CXX_FLAGS_DEBUG for the CXXFLAGS
Other important environment variables (such as LDFLAGS) are also supported.
The DESTDIR environment variable is also supported, however it needs to be set before invoking make install. For example: DESTDIR=mydestdir make install
For more information about DESTDIR, see:
* http://www.gnu.org/prep/standards/html_node/DESTDIR.html
Basic steps for installing ZoneMinder on a fresh system
-------------------------------------------------------
1) After installing all the required dependencies, in the project directory, run "cmake [extra options] ."
This behaves like ./configure. It is also possible to supply configuration options, e.g. cmake -DZM_DB_PASS="mypass" .
IMPORTANT: Don't forget the dot "." at the end.
2) Run "make" to compile ZoneMinder
3) Run "make install" (as root, or use sudo) to install ZoneMinder to your system.
4) Create a directory for the content and the necessary symlinks by running zmlinkcontent.sh with the directory you want to use. e.g. ./zmlinkcontent.sh /nfs/zm
5) Create a database for zoneminder, called "zm".
6) Create a user for the zoneminder database, called zmuser with password and full privileges to the "zm" database.
NOTE: The database server, database name, user and password can be different and adjusted during configuration step with the options in this file, or by editing /etc/zm.conf
7) Populate the zoneminder database using the script zm_create.sql. This should be found in <prefix>/share/zoneminder/db or in the project/db directory.
8) Create an apache virtual host for ZoneMinder. Make sure to use the same paths as ZM_WEBDIR and ZM_CGIDIR in /etc/zm.conf
9) Verify date.timezone is set to your timezone. This parameter is often found inside the system php.ini file. Consult your distribution's documentation for the proper way to set this value.
10) Create other config if desired (e.g. rsyslog, logrotate and such). Some of this can be found in <prefix>/share/zoneminder/misc or project/misc directory
11) Setup an appropriate startup script for your system. Two generic startup scripts have been provided, a legacy Sys V Init script and a Systemd service file.
*Sys V Init Setup*
- Copy the sys v init script /scripts/zm from the build folder to /etc/init.
- Inspect the contents to make sure they apply to your distro.
*SystemD Setup*
- Copy the zoneminder systemd service file /misc/zoneminder.service from the build folder to the systemd service file location.
For Redhat based distros, that folder is /usr/lib/systemd/system.
- Inspect the contents to make sure they apply to your distro.
- Tell systemd to load the new service file: "sudo systemctl daemon-reload".
- Copy /misc/zoneminder-tmpfiles.conf to /etc/tmpfiles.d
- Tell systemd to process this file: "sudo /usr/bin/systemd-tmpfiles --create /etc/tmpfiles.d/zoneminder.conf".
Basic steps for upgrading ZoneMinder
------------------------------------
1) If you wish to use the same paths and configuration as the currently installed ZoneMinder, you need to provide cmake with options that match your current installation.
You can provide those options in the command line to cmake, e.g. cmake -DZM_DB_PASS="blah" -DZM_WEBDIR="/usr/local/share/zoneminder/www" -DCMAKE_INSTALL_FULL_BINDIR="/usr/bin" .
Or alternatively, for convenience, use the cmakecacheimport.sh script. This reads a zoneminder configuration file (zm.conf) and creates a cmake initial cache file called zm_conf.cmake, which you can then provide to cmake.
For example:
./cmakecacheimport.sh /etc/zm.conf
cmake -C zm_conf.cmake [extra options] .
2) Run "make" to compile ZoneMinder
3) Run "make install" (as root, or use sudo) to install ZoneMinder to your system.
4) Depending on your configuration: If DIR_EVENTS is set to default, You will need to update the symlinks in the web directory to the correct folders. e.g. web directory/events should point to the real events directory.
You can use the zmlinkcontent.sh script for this. For example, if /var/lib/zoneminder is the folder that contains the "events" directory, you can use:
./zmlinkcontent.sh /var/lib/zoneminder
By default, the content directory for new installations is /var/lib/zoneminder. This can be overridden in cmake with the ZM_CONTENTDIR option. e.g. cmake -DZM_CONTENTDIR="/some/big/storage/zm" .
5) Run zmupdate.pl to update the database layout to the new version.
Uninstallation:
---------------
By default, cmake does not have an uninstall target, however we have added a one. Simply run make uninstall (or DESTDIR=mydestdir make uninstall if a DESTDIR was used) and it will remove all the files that cmake installed.
It's also possible to do this manually. The file install_manifest.txt contains the list of files installed to the system. This can be used in many ways to delete all files installed by cmake, such as: xargs rm < install_manifest.txt
Contributions:
--------------
Please visit our GitHub at http://github.com/ZoneMinder/ZoneMinder

1
NEWS
View File

@ -1 +0,0 @@
Please see README file.

View File

@ -3,7 +3,7 @@ ZoneMinder
[![Build Status](https://travis-ci.org/ZoneMinder/zoneminder.png)](https://travis-ci.org/ZoneMinder/zoneminder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received) [![Build Status](https://travis-ci.org/ZoneMinder/zoneminder.png)](https://travis-ci.org/ZoneMinder/zoneminder) [![Bountysource](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received)
[![Join Slack](https://github.com/ozonesecurity/ozonebase/blob/master/img/slacksm.png?raw=true)](https://zoneminder-chat.herokuapp.com) [![Join Slack](https://github.com/ozonesecurity/ozonebase/blob/master/img/slacksm.png?raw=true)](https://join.slack.com/t/zoneminder-chat/shared_invite/enQtNTU0NDkxMDM5NDQwLTlhZDU2MGU4MmZmN2MxOTg1MmNmNmZjZGRmY2EzMThhNGQ0MWNmZTg1ZmYzNDQ4YjliMzVmYTQ3MDc5MTkzODE)
All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org

2
TODO
View File

@ -1,2 +0,0 @@
Please see README.md file.

View File

@ -223,7 +223,7 @@ CREATE TABLE `Events_Hour` (
`EventId` BIGINT unsigned NOT NULL, `EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL, `StartTime` datetime default NULL,
`DiskSpace` bigint unsigned default NULL, `DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`), PRIMARY KEY (`EventId`),
KEY `Events_Hour_MonitorId_idx` (`MonitorId`), KEY `Events_Hour_MonitorId_idx` (`MonitorId`),
KEY `Events_Hour_StartTime_idx` (`StartTime`) KEY `Events_Hour_StartTime_idx` (`StartTime`)
@ -234,7 +234,7 @@ CREATE TABLE `Events_Day` (
`EventId` BIGINT unsigned NOT NULL, `EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL, `StartTime` datetime default NULL,
`DiskSpace` bigint unsigned default NULL, `DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`), PRIMARY KEY (`EventId`),
KEY `Events_Day_MonitorId_idx` (`MonitorId`), KEY `Events_Day_MonitorId_idx` (`MonitorId`),
KEY `Events_Day_StartTime_idx` (`StartTime`) KEY `Events_Day_StartTime_idx` (`StartTime`)
@ -245,7 +245,7 @@ CREATE TABLE `Events_Week` (
`EventId` BIGINT unsigned NOT NULL, `EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL, `StartTime` datetime default NULL,
`DiskSpace` bigint unsigned default NULL, `DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`), PRIMARY KEY (`EventId`),
KEY `Events_Week_MonitorId_idx` (`MonitorId`), KEY `Events_Week_MonitorId_idx` (`MonitorId`),
KEY `Events_Week_StartTime_idx` (`StartTime`) KEY `Events_Week_StartTime_idx` (`StartTime`)
@ -256,7 +256,7 @@ CREATE TABLE `Events_Month` (
`EventId` BIGINT unsigned NOT NULL, `EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL,
`StartTime` datetime default NULL, `StartTime` datetime default NULL,
`DiskSpace` bigint unsigned default NULL, `DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`), PRIMARY KEY (`EventId`),
KEY `Events_Month_MonitorId_idx` (`MonitorId`), KEY `Events_Month_MonitorId_idx` (`MonitorId`),
KEY `Events_Month_StartTime_idx` (`StartTime`) KEY `Events_Month_StartTime_idx` (`StartTime`)
@ -267,7 +267,7 @@ DROP TABLE IF EXISTS `Events_Archived`;
CREATE TABLE `Events_Archived` ( CREATE TABLE `Events_Archived` (
`EventId` BIGINT unsigned NOT NULL, `EventId` BIGINT unsigned NOT NULL,
`MonitorId` int(10) unsigned NOT NULL, `MonitorId` int(10) unsigned NOT NULL,
`DiskSpace` bigint unsigned default NULL, `DiskSpace` bigint default NULL,
PRIMARY KEY (`EventId`), PRIMARY KEY (`EventId`),
KEY `Events_Archived_MonitorId_idx` (`MonitorId`) KEY `Events_Archived_MonitorId_idx` (`MonitorId`)
) ENGINE=@ZM_MYSQL_ENGINE@; ) ENGINE=@ZM_MYSQL_ENGINE@;
@ -788,6 +788,7 @@ INSERT INTO `Controls` VALUES (NULL,'Trendnet','Remote','Trendnet',1,1,1,0,0,0,0
INSERT INTO `Controls` VALUES (NULL,'PSIA','Remote','PSIA',0,0,0,1,0,0,1,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,1,0,1,0,0,0,0,1,-100,100,0,0,1,0,0,0,0,1,-100,100,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'PSIA','Remote','PSIA',0,0,0,1,0,0,1,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,1,0,1,0,0,0,0,1,-100,100,0,0,1,0,0,0,0,1,-100,100,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Dahua','Remote','Dahua',0,0,0,1,0,0,1,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,1,0,1,0,0,0,0,1,1,8,0,0,1,0,0,0,0,1,1,8,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Dahua','Remote','Dahua',0,0,0,1,0,0,1,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,0,1,1,1,0,0,1,0,1,0,0,0,0,1,1,8,0,0,1,0,0,0,0,1,1,8,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'FOSCAMR2C','Libvlc','FOSCAMR2C',1,1,1,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,0,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,4,0,NULL,1,NULL,NULL,NULL,NULL,1,0,4,0,NULL,0,0); INSERT INTO `Controls` VALUES (NULL,'FOSCAMR2C','Libvlc','FOSCAMR2C',1,1,1,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,0,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,4,0,NULL,1,NULL,NULL,NULL,NULL,1,0,4,0,NULL,0,0);
INSERT INTO `Controls` VALUES (NULL,'Amcrest HTTP API','Ffmpeg','Amcrest_HTTP',0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,5,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,5);
-- --
-- Add some monitor preset values -- Add some monitor preset values

13
db/zm_update-1.33.2.sql Normal file
View File

@ -0,0 +1,13 @@
--
-- This updates a 1.33.0 database to 1.33.1
--
-- Add WebSite enum to Monitor.Type
-- Add Refresh column to Monitors table
--
ALTER TABLE `Events_Hour` MODIFY DiskSpace BIGINT default NULL;
ALTER TABLE `Events_Day` MODIFY DiskSpace BIGINT default NULL;
ALTER TABLE `Events_Week` MODIFY DiskSpace BIGINT default NULL;
ALTER TABLE `Events_Month` MODIFY DiskSpace BIGINT default NULL;
ALTER TABLE `Events_Archived` MODIFY DiskSpace BIGINT default NULL;

View File

@ -1 +0,0 @@
Zoneminder with kfir performances patches and fixes from UnixMedia (nextime)

View File

@ -1,6 +0,0 @@
ZoneMinder - A Linux based camera monitoring and analysis tool.
This project was imagined and created by Philip Coombes in
September 2002, shortly after being burglarised of his power tools.
mailto:philip.coombes@zoneminder.com

View File

@ -1 +0,0 @@
Please see README file.

View File

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -1 +0,0 @@
Please see README file.

View File

@ -1,185 +0,0 @@
Basic Installation
==================
These are generic installation instructions.
Please see http://www.zoneminder.com/wiki/index.php/Documentation
for full details.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@ -1 +0,0 @@
Please see README file.

View File

@ -1,5 +0,0 @@
All documentation for ZoneMinder is now online at
http://www.zoneminder.com/wiki/index.php/Documentation

View File

@ -1,2 +0,0 @@
Please see README file.

View File

@ -3,6 +3,205 @@ Ubuntu
.. contents:: .. contents::
Easy Way: Ubuntu 18.04
----------------------
These instructions are for a brand new ubuntu 18.04 system which does not have ZM
installed.
It is recommended that you use an Ubuntu Server install and select the LAMP option
during install to install Apache, MySQL and PHP. If you failed to do this you can
achieve the same result by running:
::
sudo tasksel install lamp-server
During installation it will ask you to set up a master/root password for the MySQL.
Installing LAMP is not ZoneMinder specific so you will find plenty of resources to
guide you with a quick search.
**Step 1:** Either run commands in this install using sudo or use the below to become root
::
sudo -i
**Step 2:** Update Repos
.. topic :: Latest Release
ZoneMinder is now part of the current standard Ubuntu repository, but
sometimes the official repository can lag behind. To find out check our
`releases page <https://github.com/ZoneMinder/zoneminder/releases>`_ for
the latest release.
Alternatively, the ZoneMinder project team maintains a `PPA <https://askubuntu.com/questions/4983/what-are-ppas-and-how-do-i-use-them>`_, which is updated immediately
following a new release of ZoneMinder. To use this repository instead of the
official Ubuntu repository, enter the following from the command line:
::
add-apt-repository ppa:iconnor/zoneminder
Please note that as of 1.32.0 We are creating a new PPA for each major version, as a means to prevent automatic upgrades from one major version to another. So instead of the above ppa line use the following:
::
add-apt-repository ppa:iconnor/zoneminder-1.32
If you are on Trusty or Xenial, you may want to add both, as there are some packages for dependencies included in the old ppa.
Update repo and upgrade.
::
apt-get update
apt-get upgrade
apt-get dist-upgrade
**Step 3:** Configure MySQL
.. sidebar :: Note
The MySQL default configuration file (/etc/mysql/mysql.cnf)is read through
several symbolic links beginning with /etc/mysql/my.cnf as follows:
| /etc/mysql/my.cnf -> /etc/alternatives/my.cnf
| /etc/alternatives/my.cnf -> /etc/mysql/mysql.cnf
| /etc/mysql/mysql.cnf is a basic file
Certain new defaults in MySQL 5.7 cause some issues with ZoneMinder < 1.32.0,
the workaround is to modify the sql_mode setting of MySQL. Please note that these
changes are NOT required for ZoneMinder 1.32.0 and some people have reported them
causing problems in 1.32.0.
To better manage the MySQL server it is recommended to copy the sample config file and
replace the default my.cnf symbolic link.
::
rm /etc/mysql/my.cnf (this removes the current symbolic link)
cp /etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/my.cnf
To change MySQL settings:
::
nano /etc/mysql/my.cnf
In the [mysqld] section add the following
::
sql_mode = NO_ENGINE_SUBSTITUTION
CTRL+o then [Enter] to save
CTRL+x to exit
Restart MySQL
::
systemctl restart mysql
**Step 4:** Install ZoneMinder
::
apt-get install zoneminder
**Step 5:** Configure the ZoneMinder Database
This step should not be required on ZoneMinder 1.32.0.
::
mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
mysql -uroot -p -e "grant lock tables,alter,drop,select,insert,update,delete,create,index,alter routine,create routine, trigger,execute on zm.* to 'zmuser'@localhost identified by 'zmpass';"
**Step 6:** Set permissions
Set /etc/zm/zm.conf to root:www-data 740 and www-data access to content
::
chmod 740 /etc/zm/zm.conf
chown root:www-data /etc/zm/zm.conf
chown -R www-data:www-data /usr/share/zoneminder/
**Step 7:** Configure Apache correctly:
::
a2enmod cgi
a2enmod rewrite
a2enconf zoneminder
You may also want to enable to following modules to improve caching performance
::
a2enmod expires
a2enmod headers
**Step 8:** Enable and start Zoneminder
::
systemctl enable zoneminder
systemctl start zoneminder
**Step 9:** Edit Timezone in PHP
::
nano /etc/php/7.2/apache2/php.ini
Search for [Date] (Ctrl + w then type Date and press Enter) and change
date.timezone for your time zone, see [this](http://php.net/manual/en/timezones.php).
**Don't forget to remove the ; from in front of date.timezone**
::
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = America/New_York
CTRL+o then [Enter] to save
CTRL+x to exit
**Step 10:** Reload Apache service
::
systemctl reload apache2
**Step 11:** Making sure ZoneMinder works
1. Open up a browser and go to ``http://hostname_or_ip/zm`` - should bring up ZoneMinder Console
2. (Optional API Check)Open up a tab in the same browser and go to ``http://hostname_or_ip/zm/api/host/getVersion.json``
If it is working correctly you should get version information similar to the example below:
::
{
"version": "1.29.0",
"apiversion": "1.29.0.1"
}
**Congratulations** Your installation is complete
PPA install may need some tweaking of ZMS_PATH in ZoneMinder options. `Socket_sendto or no live streaming`_
Easy Way: Ubuntu 16.04 Easy Way: Ubuntu 16.04
---------------------- ----------------------
These instructions are for a brand new ubuntu 16.04 system which does not have ZM These instructions are for a brand new ubuntu 16.04 system which does not have ZM

View File

@ -3,13 +3,13 @@ Options - Logging
.. image:: images/Options_Logging.png .. image:: images/Options_Logging.png
LOG_LEVEL_SYSLOG - ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to the system log. ZoneMinder binaries have always logged to the system log but now scripts and web logging is also included. To preserve the previous behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below LOG_LEVEL_SYSLOG - ZoneMinder logging is now more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to the system log. ZoneMinder binaries have always logged to the system log but now scripts and web logging is also included. To preserve the previous behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can severely affect system performance. If you want debug you will also need to set a level and component below
LOG_LEVEL_FILE - ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to individual log files written by specific components. This is how logging worked previously and although useful for tracking down issues in specific components it also resulted in many disparate log files. To preserve this behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance though file output has less impact than the other options. If you want debug you will also need to set a level and component below LOG_LEVEL_FILE - ZoneMinder logging is now more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to individual log files written by specific components. This is how logging worked previously and although useful for tracking down issues in specific components it also resulted in many disparate log files. To preserve this behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can severely affect system performance though file output has less impact than the other options. If you want debug you will also need to set a level and component below
LOG_LEVEL_WEBLOG - ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output from the web interface that goes to the httpd error log. Note that only web logging from PHP and JavaScript files is included and so this option is really only useful for investigating specific issues with those components. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below LOG_LEVEL_WEBLOG - ZoneMinder logging is now more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output from the web interface that goes to the httpd error log. Note that only web logging from PHP and JavaScript files is included and so this option is really only useful for investigating specific issues with those components. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can severely affect system performance. If you want debug you will also need to set a level and component below
LOG_LEVEL_DATABASE - ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that is written to the database. This is a new option which can make viewing logging output easier and more intuitive and also makes it easier to get an overall impression of how the system is performing. If you have a large or very busy system then it is possible that use of this option may slow your system down if the table becomes very large. Ensure you use the LOG_DATABASE_LIMIT option to keep the table to a manageable size. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below LOG_LEVEL_DATABASE - ZoneMinder logging is now more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that is written to the database. This is a new option which can make viewing logging output easier and more intuitive and also makes it easier to get an overall impression of how the system is performing. If you have a large or very busy system then it is possible that use of this option may slow your system down if the table becomes very large. Ensure you use the LOG_DATABASE_LIMIT option to keep the table to a manageable size. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can severely affect system performance. If you want debug you will also need to set a level and component below
LOG_DATABASE_LIMIT - If you are using database logging then it is possible to quickly build up a large number of entries in the Logs table. This option allows you to specify how many of these entries are kept. If you set this option to a number greater than zero then that number is used to determine the maximum number of rows, less than or equal to zero indicates no limit and is not recommended. You can also set this value to time values such as '<n> day' which will limit the log entries to those newer than that time. You can specify 'hour', 'day', 'week', 'month' and 'year', note that the values should be singular (no 's' at the end). The Logs table is pruned periodically so it is possible for more than the expected number of rows to be present briefly in the meantime. LOG_DATABASE_LIMIT - If you are using database logging then it is possible to quickly build up a large number of entries in the Logs table. This option allows you to specify how many of these entries are kept. If you set this option to a number greater than zero then that number is used to determine the maximum number of rows, less than or equal to zero indicates no limit and is not recommended. You can also set this value to time values such as '<n> day' which will limit the log entries to those newer than that time. You can specify 'hour', 'day', 'week', 'month' and 'year', note that the values should be singular (no 's' at the end). The Logs table is pruned periodically so it is possible for more than the expected number of rows to be present briefly in the meantime.

View File

@ -366,7 +366,7 @@ our @options = (
}, },
{ {
name => 'ZM_ENABLE_CSRF_MAGIC', name => 'ZM_ENABLE_CSRF_MAGIC',
default => 'no', default => 'yes',
description => 'Enable csrf-magic library', description => 'Enable csrf-magic library',
help => q` help => q`
CSRF stands for Cross-Site Request Forgery which, under specific CSRF stands for Cross-Site Request Forgery which, under specific
@ -375,11 +375,7 @@ our @options = (
this, the attacker must write a very specific web page and get this, the attacker must write a very specific web page and get
you to navigate to it, while you are logged into the ZoneMinder you to navigate to it, while you are logged into the ZoneMinder
web console at the same time. Enabling ZM_ENABLE_CSRF_MAGIC will web console at the same time. Enabling ZM_ENABLE_CSRF_MAGIC will
help mitigate these kinds of attackes. Be warned this feature help mitigate these kinds of attacks.
is experimental and may cause problems, particularly with the API.
If you find a false positive and can document how to reproduce it,
then please report it. This feature defaults to OFF currently due to
its experimental nature.
`, `,
type => $types{boolean}, type => $types{boolean},
category => 'system', category => 'system',
@ -3035,7 +3031,7 @@ our @options = (
}, },
{ {
name => 'ZM_WEB_H_REFRESH_NAVBAR', name => 'ZM_WEB_H_REFRESH_NAVBAR',
default => '5', default => '60',
description => 'How often (in seconds) the navigation header should refresh itself', description => 'How often (in seconds) the navigation header should refresh itself',
help => q` help => q`
The navigation header contains the general status information about server load and storage space. The navigation header contains the general status information about server load and storage space.
@ -3308,7 +3304,7 @@ our @options = (
}, },
{ {
name => 'ZM_WEB_M_REFRESH_NAVBAR', name => 'ZM_WEB_M_REFRESH_NAVBAR',
default => '15', default => '120',
description => 'How often (in seconds) the navigation header should refresh itself', description => 'How often (in seconds) the navigation header should refresh itself',
help => q` help => q`
The navigation header contains the general status information about server load and storage space. The navigation header contains the general status information about server load and storage space.
@ -3581,7 +3577,7 @@ our @options = (
}, },
{ {
name => 'ZM_WEB_L_REFRESH_NAVBAR', name => 'ZM_WEB_L_REFRESH_NAVBAR',
default => '35', default => '180',
description => 'How often (in seconds) the navigation header should refresh itself', description => 'How often (in seconds) the navigation header should refresh itself',
help => q` help => q`
The navigation header contains the general status information about server load and storage space. The navigation header contains the general status information about server load and storage space.

View File

@ -0,0 +1,403 @@
# ==========================================================================
#
# ZoneMinder Acrest HTTP API Control Protocol Module, 20180214, Rev 3.0
#
# Change Log
#
# Rev 3.0:
# - Fixes incorrect method names
# - Updates control sequences to Amcrest HTTP Protocol API v 2.12
# - Extends control features
#
# Rev 2.0:
# - Fixed installation instructions text, no changes to functionality.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ==========================================================================
package ZoneMinder::Control::Amcrest_HTTP;
use 5.006;
use strict;
use warnings;
use Time::HiRes qw( usleep );
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
# ==========================================================================
#
# Amcrest HTTP API Control Protocol
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
bless( $self, $class );
srand( time() );
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
Debug( "Received command: $name" );
if ( exists($self->{$name}) )
{
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
}
sub open
{
my $self = shift;
$self->loadMonitor();
$self->{state} = 'open';
}
sub initUA
{
my $self = shift;
my $user = undef;
my $password = undef;
my $address = undef;
if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ )
{
$user = $1;
$password = $2;
$address = $3;
}
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->credentials("$address", "Login to " . $self->{Monitor}->{ControlDevice}, "$user", "$password");
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
}
sub destroyUA
{
my $self = shift;
$self->{ua} = undef;
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $result = undef;
destroyUA($self);
initUA($self);
my $user = undef;
my $password = undef;
my $address = undef;
if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ )
{
$user = $1;
$password = $2;
$address = $3;
}
printMsg( $cmd, "Tx" );
my $req = HTTP::Request->new( GET=>"http://$address/$cmd" );
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
# Command to camera appears successful, write Info item to log
Info( "Camera control: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" );
# TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status.
}
else
{
Error( "Camera control command FAILED: '".$res->status_line()."' for URL ".$self->{Monitor}->{ControlAddress}."/$cmd" );
}
return( $result );
}
sub reset
{
my $self = shift;
# This reboots the camera effectively resetting it
Debug( "Camera Reset" );
$self->sendCmd( 'cgi-bin/magicBox.cgi?action=reboot' );
##FIXME: Exit is a bad idea as it appears to cause zmc to run away.
#Exit (0);
}
# NOTE: I'm putting this in, but absolute camera movement does not seem to be well supported in the classic skin ATM.
# Reading www/skins/classic/include/control_functions.php seems to indicate a faulty implementation, unless I'm
# reading it wrong. I see nowhere where the user is able to specify the absolute location to move to. Rather,
# the call is passed back movement in increments of 1 unit. At least with the Amcrest/Duhua API this would result
# in the camera moving to the 1* or 0* etc. position.
sub moveAbs ## Up, Down, Left, Right, etc. ??? Doesn't make sense here...
{
my $self = shift;
my $pan_degrees = shift || 0;
my $tilt_degrees = shift || 0;
my $speed = shift || 1;
Debug( "Move ABS" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan_degress.'&arg2='.$tilt_degrees.'&arg3=0&arg4='.$speed );
}
sub moveConUp
{
my $self = shift;
Debug( "Move Up" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Up&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500); ##XXX Should this be passed in as a "speed" parameter?
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Up&channel=0&arg1=0&arg2=1&arg3=0' );
}
sub moveConDown
{
my $self = shift;
Debug( "Move Down" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Down&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Down&channel=0&arg1=0&arg2=1&arg3=0' );
}
sub moveConLeft
{
my $self = shift;
Debug( "Move Left" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Left&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Left&channel=0&arg1=0&arg2=1&arg3=0' );
}
sub moveConRight
{
my $self = shift;
Debug( "Move Right" );
# $self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=270&arg2=5&arg3=0' );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=Right&channel=0&arg1=0&arg2=1&arg3=0' );
usleep (500);
Debug( "Move Right Stop" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=Right&channel=0&arg1=0&arg2=1&arg3=0' );
}
sub moveConUpRight
{
my $self = shift;
Debug( "Move Diagonally Up Right" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightUp&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightUp&channel=0&arg1=0&arg2=1&arg3=0' );
}
sub moveConDownRight
{
my $self = shift;
Debug( "Move Diagonally Down Right" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=RightDown&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=RightDown&channel=0&arg1=0&arg2=1&arg3=0' );
}
sub moveConUpLeft
{
my $self = shift;
Debug( "Move Diagonally Up Left" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftUp&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftUp&channel=0&arg1=0&arg2=1&arg3=0' );
}
sub moveConDownLeft
{
my $self = shift;
Debug( "Move Diagonally Down Left" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=LeftDown&channel=0&arg1=1&arg2=1&arg3=0' );
usleep (500);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&code=LeftDown&channel=0&arg1=0&arg2=1&arg3=0' );
}
# Stop is not "correctly" implemented as control_functions.php translates this to "Center"
# So we'll just send the camera to 0* Horz, 0* Vert, zoom out; Also, Amcrest does not seem to
# support a generic stop-all-current-action command.
sub moveStop
{
my $self = shift;
Debug( "Move Stop/Center" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1=0&arg2=0&arg3=0&arg4=1' );
}
# Move Camera to Home Position
# The current API does not support a Home per se, so we'll just send the camera to preset #1
# NOTE: It goes without saying that the user must have set up preset #1 for this to work.
sub presetHome
{
my $self = shift;
Debug( "Home Preset" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2=1&arg3=0&arg4=0' );
}
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Go To Preset $preset" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' );
}
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=SetPreset&arg1=0&arg2='.$preset.'&arg3=0&arg4=0' );
}
# NOTE: This does not appear to be implemented in the classic skin. But we'll leave it here for later.
sub moveMap
{
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord', $self->{Monitor}{Width}/2 );
my $ycoord = $self->getParam( $params, 'ycoord', $self->{Monitor}{Height}/2 );
# if the camera is mounted upside down, you may have to inverse these coordinates
# just use 360 minus pan instead of pan, 90 minus tilt instead of tilt
# Convert xcoord into pan position 0 to 359
my $pan = int(360 * $xcoord / $self->{Monitor}{Width});
# Convert ycoord into tilt position 0 to 89
my $tilt = 90 - int(90 * $ycoord / $self->{Monitor}{Height});
# Now get the following url:
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&code=PositionABS&channel=0&arg1='.$pan.'&arg2='.$tilt.'&arg3=1&arg4=1');
}
sub zoomConTele
{
my $self = shift;
Debug( "Zoom continuous tele" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' );
usleep (100000);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomTele&arg1=0&arg2=0&arg3=0&arg4=0' );
}
sub zoomConWide
{
my $self = shift;
Debug( "Zoom continuous wide" );
$self->sendCmd( 'cgi-bin/ptz.cgi?action=start&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' );
usleep (100000);
$self->sendCmd( 'cgi-bin/ptz.cgi?action=stop&channel=0&code=ZoomWide&arg1=0&arg2=0&arg3=0&arg4=0' );
}
1;
__END__
=pod
=head1 NAME
ZoneMinder::Control::Amcrest_HTTP - Amcrest camera control
=head1 DESCRIPTION
This module contains the implementation of the Amcrest Camera
controllable SDK API.
NOTE: This module implements interaction with the camera in clear text.
The login and password are transmitted from ZM to the camera in clear text,
and as such, this module should be used ONLY on a blind LAN implementation
where interception of the packets is very low risk.
The "usleep (X);" lines throughout the script may need adjustments for your
situation. This is the time that the script waits between sending a "start"
and a "stop" signal to the camera. For example, the pan left arrow would
result in the camera panning full to its leftmost position if there were no
stop signal. So the usleep time sets how long the script waits to allow the
camera to start moving before issuing a stop. The X value of usleep is in
microseconds, so "usleep (100000);" is equivalent to wait one second.
=head1 SEE ALSO
https://s3.amazonaws.com/amcrest-files/Amcrest+HTTP+API+3.2017.pdf
=head1 AUTHORS
Herndon Elliott alabamatoy at gmail dot com
Chris Nighswonger chris dot nighswonger at gmail dot com
=head1 COPYRIGHT AND LICENSE
(C) 2016 Herndon Elliott alabamatoy at gmail dot com
(C) 2018 Chris Nighswonger chris dot nighswonger at gmail dot com
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
=cut

View File

@ -696,10 +696,15 @@ sub error {
} }
sub Fatal( @ ) { sub Fatal( @ ) {
fetch()->logPrint(FATAL, @_, caller); my $this = fetch();
$this->logPrint(FATAL, @_, caller);
if ( $SIG{TERM} and ( $SIG{TERM} ne 'DEFAULT' ) ) { if ( $SIG{TERM} and ( $SIG{TERM} ne 'DEFAULT' ) ) {
$SIG{TERM}(); $SIG{TERM}();
} }
if ( $$this{sth} ) {
$$this{sth}->finish();
$$this{sth} = undef;
}
# I think if we don't disconnect we will leave sockets around in TIME_WAIT # I think if we don't disconnect we will leave sockets around in TIME_WAIT
ZoneMinder::Database::zmDbDisconnect(); ZoneMinder::Database::zmDbDisconnect();
exit(-1); exit(-1);

View File

@ -319,12 +319,15 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
/* the pid is an important information, so we display it */ /* the pid is an important information, so we display it */
/* XXX: add a generic system */ /* XXX: add a generic system */
if (flags & AVFMT_SHOW_IDS) if (flags & AVFMT_SHOW_IDS)
Debug(1, "[0x%x]", st->id); Debug(1, "ids [0x%x]", st->id);
if (lang) if (lang)
Debug(1, "(%s)", lang->value); Debug(1, "lang:%s", lang->value);
Debug(1, ", frames:%d, timebase: %d/%d", st->codec_info_nb_frames, st->time_base.num, st->time_base.den); Debug(1, "frames:%d, stream timebase: %d/%d codec timebase: %d/%d",
st->codec_info_nb_frames, st->time_base.num, st->time_base.den,
st->codec->time_base.num, st->codec->time_base.den
);
avcodec_string(buf, sizeof(buf), st->codec, is_output); avcodec_string(buf, sizeof(buf), st->codec, is_output);
Debug(1, ": %s", buf); Debug(1, "codec: %s", buf);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
AVCodecParameters *codec = st->codecpar; AVCodecParameters *codec = st->codecpar;
#else #else
@ -348,13 +351,10 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
int tbn = st->time_base.den && st->time_base.num; int tbn = st->time_base.den && st->time_base.num;
int tbc = st->codec->time_base.den && st->codec->time_base.num; int tbc = st->codec->time_base.den && st->codec->time_base.num;
if (fps || tbn || tbc)
Debug(3, "\n" );
if (fps) if (fps)
zm_log_fps(av_q2d(st->avg_frame_rate), tbn || tbc ? "fps, " : "fps"); zm_log_fps(av_q2d(st->avg_frame_rate), "fps");
if (tbn) if (tbn)
zm_log_fps(1 / av_q2d(st->time_base), tbc ? "stream tb numerator , " : "stream tb numerator"); zm_log_fps(1 / av_q2d(st->time_base), "stream tb numerator");
if (tbc) if (tbc)
zm_log_fps(1 / av_q2d(st->codec->time_base), "codec time base:"); zm_log_fps(1 / av_q2d(st->codec->time_base), "codec time base:");
} }
@ -379,7 +379,6 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
Debug(1, " (visual impaired)"); Debug(1, " (visual impaired)");
if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS) if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
Debug(1, " (clean effects)"); Debug(1, " (clean effects)");
Debug(1, "\n");
//dump_metadata(NULL, st->metadata, " "); //dump_metadata(NULL, st->metadata, " ");

View File

@ -439,11 +439,13 @@ int FfmpegCamera::OpenFfmpeg() {
Debug(3, "Found audio stream at index %d", mAudioStreamId); Debug(3, "Found audio stream at index %d", mAudioStreamId);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
mVideoCodecContext = avcodec_alloc_context3(NULL); //mVideoCodecContext = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context( mVideoCodecContext, mFormatContext->streams[mVideoStreamId]->codecpar ); //avcodec_parameters_to_context( mVideoCodecContext, mFormatContext->streams[mVideoStreamId]->codecpar );
// this isn't copied.
//mVideoCodecContext->time_base = mFormatContext->streams[mVideoStreamId]->codec->time_base;
#else #else
mVideoCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
#endif #endif
mVideoCodecContext = mFormatContext->streams[mVideoStreamId]->codec;
// STolen from ispy // STolen from ispy
//this fixes issues with rtsp streams!! woot. //this fixes issues with rtsp streams!! woot.
//mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode. //mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode.
@ -486,16 +488,6 @@ int FfmpegCamera::OpenFfmpeg() {
} }
} }
} }
} else {
#ifdef AV_CODEC_ID_H265
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H265 ) {
Debug( 1, "Input stream appears to be h265. The stored event file may not be viewable in browser." );
} else {
#endif
Warning( "Input stream is not h264. The stored event file may not be viewable in browser." );
#ifdef AV_CODEC_ID_H265
}
#endif
} // end if h264 } // end if h264
#endif #endif
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) { if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
@ -516,11 +508,12 @@ int FfmpegCamera::OpenFfmpeg() {
// Open the codec // Open the codec
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
Debug(1, "Calling avcodec_open"); Debug(1, "Calling avcodec_open");
if ( avcodec_open(mVideoCodecContext, mVideoCodec) < 0 ){ if ( avcodec_open(mVideoCodecContext, mVideoCodec) < 0 )
#else #else
Debug(1, "Calling avcodec_open2"); Debug(1, "Calling avcodec_open2");
if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 ) { if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 )
#endif #endif
{
AVDictionaryEntry *e = NULL; AVDictionaryEntry *e = NULL;
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning( "Option %s not recognized by ffmpeg", e->key); Warning( "Option %s not recognized by ffmpeg", e->key);
@ -656,8 +649,9 @@ int FfmpegCamera::Close() {
if ( mVideoCodecContext ) { if ( mVideoCodecContext ) {
avcodec_close(mVideoCodecContext); avcodec_close(mVideoCodecContext);
Debug(1,"After codec close");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&mVideoCodecContext); //avcodec_free_context(&mVideoCodecContext);
#endif #endif
mVideoCodecContext = NULL; // Freed by av_close_input_file mVideoCodecContext = NULL; // Freed by av_close_input_file
} }

View File

@ -245,3 +245,18 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) {
Debug(1, "No user found for auth_key %s", auth ); Debug(1, "No user found for auth_key %s", auth );
return 0; return 0;
} }
//Function to check Username length
bool checkUser ( const char *username) {
if ( strlen(username) > 32) {
return false;
}
return true;
}
//Function to check password length
bool checkPass (const char *password) {
if ( strlen(password) > 64) {
return false;
}
return true;
}

View File

@ -77,5 +77,7 @@ public:
User *zmLoadUser( const char *username, const char *password=0 ); User *zmLoadUser( const char *username, const char *password=0 );
User *zmLoadAuthUser( const char *auth, bool use_remote_addr ); User *zmLoadAuthUser( const char *auth, bool use_remote_addr );
bool checkUser ( const char *username);
bool checkPass (const char *password);
#endif // ZM_USER_H #endif // ZM_USER_H

View File

@ -31,21 +31,26 @@ extern "C" {
#include "libavutil/time.h" #include "libavutil/time.h"
} }
VideoStore::VideoStore(const char *filename_in, const char *format_in, VideoStore::VideoStore(
const char *filename_in,
const char *format_in,
AVStream *p_video_in_stream, AVStream *p_video_in_stream,
AVStream *p_audio_in_stream, int64_t nStartTime, AVStream *p_audio_in_stream,
Monitor *monitor) { int64_t nStartTime,
Monitor *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;
#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);
avcodec_parameters_to_context(video_in_ctx, //avcodec_parameters_to_context(video_in_ctx,
video_in_stream->codecpar); //video_in_stream->codecpar);
//video_in_ctx->time_base = video_in_stream->time_base;
// zm_dump_codecpar( video_in_stream->codecpar ); // zm_dump_codecpar( video_in_stream->codecpar );
#else #else
video_in_ctx = video_in_stream->codec;
#endif #endif
video_in_ctx = video_in_stream->codec;
// store ins in variables local to class // store ins in variables local to class
filename = filename_in; filename = filename_in;
@ -85,16 +90,16 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
oc->metadata = pmetadata; oc->metadata = pmetadata;
out_format = oc->oformat; out_format = oc->oformat;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if 0
//LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Since we are not re-encoding, all we have to do is copy the parameters // Since we are not re-encoding, all we have to do is copy the parameters
video_out_ctx = avcodec_alloc_context3(NULL); video_out_ctx = avcodec_alloc_context3(NULL);
// Copy params from instream to ctx // Copy params from instream to ctx
ret = avcodec_parameters_to_context(video_out_ctx, ret = avcodec_parameters_to_context(video_out_ctx, video_in_stream->codecpar);
video_in_stream->codecpar);
if ( ret < 0 ) { if ( ret < 0 ) {
Error("Could not initialize ctx parameteres"); Error("Could not initialize video_out_ctx parameters");
return; return;
} else { } else {
zm_dump_codec(video_out_ctx); zm_dump_codec(video_out_ctx);
@ -102,7 +107,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_out_stream = avformat_new_stream(oc, NULL); video_out_stream = avformat_new_stream(oc, NULL);
if ( !video_out_stream ) { if ( !video_out_stream ) {
Error("Unable to create video out stream\n"); Error("Unable to create video out stream");
return; return;
} else { } else {
Debug(2, "Success creating video out stream"); Debug(2, "Success creating video out stream");
@ -163,6 +168,20 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_out_ctx->time_base = AV_TIME_BASE_Q; video_out_ctx->time_base = AV_TIME_BASE_Q;
} }
video_out_stream->time_base = video_in_stream->time_base; video_out_stream->time_base = video_in_stream->time_base;
if ( video_in_stream->avg_frame_rate.num ) {
Debug(3,"Copying avg_frame_rate (%d/%d)",
video_in_stream->avg_frame_rate.num,
video_in_stream->avg_frame_rate.den
);
video_out_stream->avg_frame_rate = video_in_stream->avg_frame_rate;
}
if ( video_in_stream->r_frame_rate.num ) {
Debug(3,"Copying r_frame_rate (%d/%d)",
video_in_stream->r_frame_rate.num,
video_in_stream->r_frame_rate.den
);
video_out_stream->r_frame_rate = video_in_stream->r_frame_rate;
}
Debug(3, Debug(3,
"Time bases: VIDEO in stream (%d/%d) in codec: (%d/%d) out " "Time bases: VIDEO in stream (%d/%d) in codec: (%d/%d) out "
@ -170,8 +189,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
video_in_stream->time_base.num, video_in_stream->time_base.den, video_in_stream->time_base.num, video_in_stream->time_base.den,
video_in_ctx->time_base.num, video_in_ctx->time_base.den, video_in_ctx->time_base.num, video_in_ctx->time_base.den,
video_out_stream->time_base.num, video_out_stream->time_base.den, video_out_stream->time_base.num, video_out_stream->time_base.den,
video_out_ctx->time_base.num, video_out_ctx->time_base.num, video_out_ctx->time_base.den);
video_out_ctx->time_base.den);
if (oc->oformat->flags & AVFMT_GLOBALHEADER) { if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
@ -207,6 +225,9 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
out_frame = NULL; out_frame = NULL;
#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE) #if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
resample_ctx = NULL; resample_ctx = NULL;
#if defined(HAVE_LIBSWRESAMPLE)
fifo = NULL;
#endif
#endif #endif
if ( audio_in_stream ) { if ( audio_in_stream ) {
@ -216,6 +237,7 @@ VideoStore::VideoStore(const char *filename_in, const char *format_in,
audio_in_ctx = avcodec_alloc_context3(NULL); audio_in_ctx = avcodec_alloc_context3(NULL);
ret = avcodec_parameters_to_context(audio_in_ctx, ret = avcodec_parameters_to_context(audio_in_ctx,
audio_in_stream->codecpar); audio_in_stream->codecpar);
audio_in_ctx->time_base = audio_in_stream->time_base;
#else #else
audio_in_ctx = audio_in_stream->codec; audio_in_ctx = audio_in_stream->codec;
#endif #endif
@ -323,7 +345,7 @@ bool VideoStore::open() {
AVDictionary *opts = NULL; AVDictionary *opts = NULL;
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); // av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
// av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0); av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
// av_dict_set(&opts, "movflags", // av_dict_set(&opts, "movflags",
// "frag_keyframe+empty_moov+default_base_moof", 0); // "frag_keyframe+empty_moov+default_base_moof", 0);
if ((ret = avformat_write_header(oc, &opts)) < 0) { if ((ret = avformat_write_header(oc, &opts)) < 0) {
@ -437,13 +459,13 @@ VideoStore::~VideoStore() {
if ( video_out_stream ) { if ( video_out_stream ) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it // We allocate and copy in newer ffmpeg, so need to free it
avcodec_free_context(&video_in_ctx); //avcodec_free_context(&video_in_ctx);
#endif #endif
video_in_ctx = NULL; video_in_ctx = NULL;
avcodec_close(video_out_ctx); avcodec_close(video_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&video_out_ctx); //avcodec_free_context(&video_out_ctx);
#endif #endif
video_out_ctx = NULL; video_out_ctx = NULL;
Debug(4, "Success freeing video_out_ctx"); Debug(4, "Success freeing video_out_ctx");
@ -467,6 +489,10 @@ VideoStore::~VideoStore() {
#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE) #if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE)
if ( resample_ctx ) { if ( resample_ctx ) {
#if defined(HAVE_LIBSWRESAMPLE) #if defined(HAVE_LIBSWRESAMPLE)
if ( fifo ) {
av_audio_fifo_free(fifo);
fifo = NULL;
}
swr_free(&resample_ctx); swr_free(&resample_ctx);
#else #else
#if defined(HAVE_LIBAVRESAMPLE) #if defined(HAVE_LIBAVRESAMPLE)
@ -540,6 +566,7 @@ bool VideoStore::setup_resampler() {
audio_out_ctx = audio_out_stream->codec; audio_out_ctx = audio_out_stream->codec;
#endif #endif
// Some formats (i.e. WAV) do not produce the proper channel layout // Some formats (i.e. WAV) do not produce the proper channel layout
// Perhaps we should not be modifying the audio_in_ctx....
if ( audio_in_ctx->channel_layout == 0 ) if ( audio_in_ctx->channel_layout == 0 )
audio_in_ctx->channel_layout = av_get_channel_layout("mono"); audio_in_ctx->channel_layout = av_get_channel_layout("mono");
@ -613,6 +640,12 @@ bool VideoStore::setup_resampler() {
} }
#endif #endif
Debug(1,
"Audio in bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) "
"layout(%d) frame_size(%d)",
audio_in_ctx->bit_rate, audio_in_ctx->sample_rate,
audio_in_ctx->channels, audio_in_ctx->sample_fmt,
audio_in_ctx->channel_layout, audio_in_ctx->frame_size);
Debug(1, Debug(1,
"Audio out bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) " "Audio out bit_rate (%d) sample_rate(%d) channels(%d) fmt(%d) "
"layout(%d) frame_size(%d)", "layout(%d) frame_size(%d)",
@ -634,11 +667,17 @@ bool VideoStore::setup_resampler() {
} }
#if defined(HAVE_LIBSWRESAMPLE) #if defined(HAVE_LIBSWRESAMPLE)
if (!(fifo = av_audio_fifo_alloc(
audio_out_ctx->sample_fmt,
audio_out_ctx->channels, 1))) {
Error("Could not allocate FIFO");
return false;
}
resample_ctx = swr_alloc_set_opts(NULL, resample_ctx = swr_alloc_set_opts(NULL,
av_get_default_channel_layout(audio_out_ctx->channels), audio_out_ctx->channel_layout,
audio_out_ctx->sample_fmt, audio_out_ctx->sample_fmt,
audio_out_ctx->sample_rate, audio_out_ctx->sample_rate,
av_get_default_channel_layout(audio_in_ctx->channels), audio_in_ctx->channel_layout,
audio_in_ctx->sample_fmt, audio_in_ctx->sample_fmt,
audio_in_ctx->sample_rate, audio_in_ctx->sample_rate,
0, NULL); 0, NULL);
@ -695,7 +734,9 @@ bool VideoStore::setup_resampler() {
out_frame->nb_samples = audio_out_ctx->frame_size; out_frame->nb_samples = audio_out_ctx->frame_size;
out_frame->format = audio_out_ctx->sample_fmt; out_frame->format = audio_out_ctx->sample_fmt;
out_frame->channels = audio_out_ctx->channels;
out_frame->channel_layout = audio_out_ctx->channel_layout; out_frame->channel_layout = audio_out_ctx->channel_layout;
out_frame->sample_rate = audio_out_ctx->sample_rate;
// The codec gives us the frame size, in samples, we calculate the size of the // The codec gives us the frame size, in samples, we calculate the size of the
// samples buffer in bytes // samples buffer in bytes
@ -713,7 +754,8 @@ bool VideoStore::setup_resampler() {
} }
// Setup the data pointers in the AVFrame // Setup the data pointers in the AVFrame
if ( avcodec_fill_audio_frame(out_frame, audio_out_ctx->channels, if ( avcodec_fill_audio_frame(
out_frame, audio_out_ctx->channels,
audio_out_ctx->sample_fmt, audio_out_ctx->sample_fmt,
(const uint8_t *)converted_in_samples, (const uint8_t *)converted_in_samples,
audioSampleBuffer_size, 0) < 0) { audioSampleBuffer_size, 0) < 0) {
@ -896,10 +938,14 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0; return 0;
} }
Debug(2, Debug(2,
"Input Frame: samples(%d), format(%d), sample_rate(%d), channel " "In Frame: samples(%d), format(%d), sample_rate(%d), "
"layout(%d)", "channels(%d) channel layout(%d) pts(%" PRId64 ")",
in_frame->nb_samples, in_frame->format, in_frame->nb_samples,
in_frame->sample_rate, in_frame->channel_layout); in_frame->format,
in_frame->sample_rate,
in_frame->channels,
in_frame->channel_layout,
in_frame->pts);
#else #else
/** /**
* Decode the audio frame stored in the packet. * Decode the audio frame stored in the packet.
@ -921,32 +967,63 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0; return 0;
} }
#endif #endif
int frame_size = out_frame->nb_samples; int frame_size = in_frame->nb_samples;
// Resample the in into the audioSampleBuffer until we proceed the whole // Resample the in into the audioSampleBuffer until we proceed the whole
// decoded data // decoded data
Debug(2, "Converting %d to %d samples", in_frame->nb_samples, out_frame->nb_samples); Debug(2, "Converting %d to %d samples", in_frame->nb_samples, out_frame->nb_samples);
if (
#if defined(HAVE_LIBSWRESAMPLE) #if defined(HAVE_LIBSWRESAMPLE)
(ret = swr_convert(resample_ctx, #if 0
ret = swr_convert(resample_ctx,
out_frame->data, frame_size, out_frame->data, frame_size,
(const uint8_t**)in_frame->data, (const uint8_t**)in_frame->data,
in_frame->nb_samples)) in_frame->nb_samples
);
#else
ret = swr_convert_frame(resample_ctx, out_frame, in_frame);
av_frame_unref(in_frame);
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
return 0;
}
#endif
if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples)) < 0) {
Error("Could not reallocate FIFO");
return 0;
}
/** Store the new samples in the FIFO buffer. */
ret = av_audio_fifo_write(fifo, (void **)out_frame->data, out_frame->nb_samples);
if ( ret < frame_size ) {
Error("Could not write data to FIFO on %d written", ret);
return 0;
}
// Reset frame_size to output_frame_size
frame_size = audio_out_ctx->frame_size;
// AAC requires 1024 samples per encode. Our input tends to be 160, so need to buffer them.
if ( frame_size > av_audio_fifo_size(fifo) ) {
return 0;
}
if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) < frame_size ) {
Error("Could not read data from FIFO");
return 0;
}
out_frame->nb_samples = frame_size;
/// FIXME this is not the correct pts
out_frame->pts = in_frame->pts;
#else #else
#if defined(HAVE_LIBAVRESAMPLE) #if defined(HAVE_LIBAVRESAMPLE)
(ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data, (ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
0, in_frame->nb_samples)) 0, in_frame->nb_samples))
#endif av_frame_unref(in_frame);
#endif if ( ret < 0 ) {
< 0) {
Error("Could not resample frame (error '%s')", Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
av_frame_unref(in_frame);
return 0; return 0;
} }
av_frame_unref(in_frame);
#if defined(HAVE_LIBAVRESAMPLE)
int samples_available = avresample_available(resample_ctx); int samples_available = avresample_available(resample_ctx);
if ( samples_available < frame_size ) { if ( samples_available < frame_size ) {
@ -962,10 +1039,15 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0; return 0;
} }
#endif #endif
#endif
Debug(2, Debug(2,
"Frame: samples(%d), format(%d), sample_rate(%d), channel layout(%d)", "Out Frame: samples(%d), format(%d), sample_rate(%d), "
"channels(%d) channel layout(%d) pts(%" PRId64 ")",
out_frame->nb_samples, out_frame->format, out_frame->nb_samples, out_frame->format,
out_frame->sample_rate, out_frame->channel_layout); out_frame->sample_rate,
out_frame->channels,
out_frame->channel_layout,
out_frame->pts);
av_init_packet(&opkt); av_init_packet(&opkt);
Debug(5, "after init packet"); Debug(5, "after init packet");
@ -982,7 +1064,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
if ( (ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0 ) { if ( (ret = avcodec_receive_packet(audio_out_ctx, &opkt)) < 0 ) {
if ( AVERROR(EAGAIN) == ret ) { if ( AVERROR(EAGAIN) == ret ) {
// THe codec may need more samples than it has, perfectly valid // The codec may need more samples than it has, perfectly valid
Debug(3, "Could not recieve packet (error '%s')", Debug(3, "Could not recieve packet (error '%s')",
av_make_error_string(ret).c_str()); av_make_error_string(ret).c_str());
} else { } else {

View File

@ -5,6 +5,7 @@
extern "C" { extern "C" {
#ifdef HAVE_LIBSWRESAMPLE #ifdef HAVE_LIBSWRESAMPLE
#include "libswresample/swresample.h" #include "libswresample/swresample.h"
#include "libavutil/audio_fifo.h"
#else #else
#ifdef HAVE_LIBAVRESAMPLE #ifdef HAVE_LIBAVRESAMPLE
#include "libavresample/avresample.h" #include "libavresample/avresample.h"
@ -44,6 +45,7 @@ private:
AVCodecContext *audio_out_ctx; AVCodecContext *audio_out_ctx;
#ifdef HAVE_LIBSWRESAMPLE #ifdef HAVE_LIBSWRESAMPLE
SwrContext *resample_ctx; SwrContext *resample_ctx;
AVAudioFifo *fifo;
#else #else
#ifdef HAVE_LIBAVRESAMPLE #ifdef HAVE_LIBAVRESAMPLE
AVAudioResampleContext* resample_ctx; AVAudioResampleContext* resample_ctx;

View File

@ -191,9 +191,12 @@ int main( int argc, const char *argv[] ) {
User *user = 0; User *user = 0;
if ( strcmp(config.auth_relay, "none") == 0 ) { if ( strcmp(config.auth_relay, "none") == 0 ) {
if ( username.length() ) { if ( checkUser(username.c_str()) ) {
user = zmLoadUser(username.c_str()); user = zmLoadUser(username.c_str());
} else {
Error("")
} }
} else { } else {
//if ( strcmp( config.auth_relay, "hashed" ) == 0 ) //if ( strcmp( config.auth_relay, "hashed" ) == 0 )
{ {

View File

@ -425,6 +425,10 @@ int main(int argc, char *argv[]) {
if ( config.opt_use_auth ) { if ( config.opt_use_auth ) {
if ( strcmp(config.auth_relay, "none") == 0 ) { if ( strcmp(config.auth_relay, "none") == 0 ) {
if ( !checkUser(username)) {
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
exit_zmu(-1);
}
if ( !username ) { if ( !username ) {
fprintf(stderr, "Error, username must be supplied\n"); fprintf(stderr, "Error, username must be supplied\n");
exit_zmu(-1); exit_zmu(-1);
@ -438,7 +442,14 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Error, username and password or auth string must be supplied\n"); fprintf(stderr, "Error, username and password or auth string must be supplied\n");
exit_zmu(-1); exit_zmu(-1);
} }
if ( !checkUser(username)) {
fprintf(stderr, "Error, username greater than allowed 32 characters\n");
exit_zmu(-1);
}
if ( !checkPass(password)) {
fprintf(stderr, "Error, password greater than allowed 64 characters\n");
exit_zmu(-1);
}
//if ( strcmp( config.auth_relay, "hashed" ) == 0 ) //if ( strcmp( config.auth_relay, "hashed" ) == 0 )
{ {
if ( auth ) { if ( auth ) {

View File

@ -1,16 +0,0 @@
#!/bin/bash
#http://tom.webarts.ca/Blog/new-blog-items/buildingzoneminderandrequiredffmpegandx264fromsource
export LD_LIBRARY_PATH="/usr/local/lib:/opt/libjpeg-turbo/lib:$LD_LIBRARY_PATH"
export LDFLAGS=" -L/home/nextime/zm/libjpeg-turbo-1.2.1/.libs "
DEB_HOST_GNU_TYPE=$(dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE=$(dpkg-architecture -qDEB_BUILD_GNU_TYPE)
CXXFLAGS=" -DZM_FFMPEG_CVS -DHAVE_LIBCRYPTO -msse2 -DJPEG_INCLUDE_DIR=/home/nextime/zm/libjpeg-turbo-1.2.1/ "
CXXFLAGS="$CXXFLAGS -I/home/nextime/zm/libjpeg-turbo-1.2.1/ "
CXXFLAGS="$CXXFLAGS" ./configure --with-libarch=lib/$DEB_HOST_GNU_TYPE --disable-debug --host=$DEB_HOST_GNU_TYPE --build=$DEB_BUILD_GNU_TYPE --sysconfdir=/etc/zm --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --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-crashtrace=no --enable-mmap=yes

View File

@ -1 +1 @@
1.33.1 1.33.2

View File

@ -1,6 +1,6 @@
<?php <?php
$defaultMonitor = new Monitor(); $defaultMonitor = new ZM\Monitor();
$defaultMonitor->set(array( $defaultMonitor->set(array(
'StorageId' => 1, 'StorageId' => 1,
'ServerId' => 'auto', 'ServerId' => 'auto',
@ -19,11 +19,11 @@ function probe( &$url_bits ) {
$cam_list_html = file_get_contents('http://'.$url_bits['host'].':5000/monitoring/'); $cam_list_html = file_get_contents('http://'.$url_bits['host'].':5000/monitoring/');
if ( $cam_list_html ) { if ( $cam_list_html ) {
Logger::Debug("Have content at port 5000/monitoring"); ZM\Logger::Debug("Have content at port 5000/monitoring");
$matches_count = preg_match_all( $matches_count = preg_match_all(
'/<a href="http:\/\/([.[:digit:]]+):([[:digit:]]+)\/\?action=stream" target="_blank">([^<]+)<\/a>/', '/<a href="http:\/\/([.[:digit:]]+):([[:digit:]]+)\/\?action=stream" target="_blank">([^<]+)<\/a>/',
$cam_list_html, $cam_list ); $cam_list_html, $cam_list );
Logger::Debug(print_r($cam_list,true)); ZM\Logger::Debug(print_r($cam_list,true));
} }
if ( $matches_count ) { if ( $matches_count ) {
for( $index = 0; $index < $matches_count; $index ++ ) { for( $index = 0; $index < $matches_count; $index ++ ) {
@ -33,10 +33,10 @@ function probe( &$url_bits ) {
if ( ! isset($new_stream['scheme'] ) ) if ( ! isset($new_stream['scheme'] ) )
$new_stream['scheme'] = 'http'; $new_stream['scheme'] = 'http';
$available_streams[] = $new_stream; $available_streams[] = $new_stream;
Logger::Debug("Have new stream " . print_r($new_stream,true) ); ZM\Logger::Debug("Have new stream " . print_r($new_stream,true) );
} }
} else { } else {
Info('No matches'); ZM\Info('No matches');
} }
if ( 0 ) { if ( 0 ) {
// No port given, do a port scan // No port given, do a port scan
@ -57,7 +57,7 @@ Info("Testing connection to " . $url_bits['host'].':'.$port);
$new_stream['port'] = $port; $new_stream['port'] = $port;
} else { } else {
socket_close($socket); socket_close($socket);
Info("No connection to ".$url_bits['host'] . " on port $port"); ZM\Info("No connection to ".$url_bits['host'] . " on port $port");
continue; continue;
} }
if ( $new_stream ) { if ( $new_stream ) {
@ -65,7 +65,7 @@ Info("Testing connection to " . $url_bits['host'].':'.$port);
$new_stream['scheme'] = 'http'; $new_stream['scheme'] = 'http';
$url = unparse_url($new_stream, array('path'=>'/', 'query'=>'action=snapshot')); $url = unparse_url($new_stream, array('path'=>'/', 'query'=>'action=snapshot'));
list($width, $height, $type, $attr) = getimagesize( $url ); list($width, $height, $type, $attr) = getimagesize( $url );
Info("Got $width x $height from $url"); ZM\Info("Got $width x $height from $url");
$new_stream['Width'] = $width; $new_stream['Width'] = $width;
$new_stream['Height'] = $height; $new_stream['Height'] = $height;
@ -93,9 +93,9 @@ Info("Testing connection to " . $url_bits['host'].':'.$port);
foreach ( $available_streams as &$stream ) { foreach ( $available_streams as &$stream ) {
# check for existence in db. # check for existence in db.
$stream['url'] = unparse_url( $stream, array('path'=>'/','query'=>'action=stream') ); $stream['url'] = unparse_url( $stream, array('path'=>'/','query'=>'action=stream') );
$monitors = Monitor::find( array('Path'=>$stream['url']) ); $monitors = ZM\Monitor::find( array('Path'=>$stream['url']) );
if ( count($monitors) ) { if ( count($monitors) ) {
Info("Found monitors matching " . $stream['url'] ); ZM\Info("Found monitors matching " . $stream['url'] );
$stream['Monitor'] = $monitors[0]; $stream['Monitor'] = $monitors[0];
if ( isset( $stream['Width'] ) and ( $stream['Monitor']->Width() != $stream['Width'] ) ) { if ( isset( $stream['Width'] ) and ( $stream['Monitor']->Width() != $stream['Width'] ) ) {
$stream['Warning'] .= 'Monitor width ('.$stream['Monitor']->Width().') and stream width ('.$stream['Width'].") do not match!\n"; $stream['Warning'] .= 'Monitor width ('.$stream['Monitor']->Width().') and stream width ('.$stream['Width'].") do not match!\n";
@ -135,9 +135,9 @@ if ( canEdit( 'Monitors' ) ) {
if ( 0 ) { if ( 0 ) {
// Shortcut test // Shortcut test
$monitors = Monitor::find( array('Path'=>$_REQUEST['url']) ); $monitors = ZM\Monitor::find( array('Path'=>$_REQUEST['url']) );
if ( count( $monitors ) ) { if ( count( $monitors ) ) {
Info("Monitor found for " . $_REQUEST['url']); ZM\Info("Monitor found for " . $_REQUEST['url']);
$url_bits['url'] = $_REQUEST['url']; $url_bits['url'] = $_REQUEST['url'];
$url_bits['Monitor'] = $monitors[0]; $url_bits['Monitor'] = $monitors[0];
$available_stream[] = $url_bits; $available_stream[] = $url_bits;
@ -174,7 +174,7 @@ if ( 0 ) {
$name = $data[0]; $name = $data[0];
$url = $data[1]; $url = $data[1];
$group = $data[2]; $group = $data[2];
Info("Have the following line data $name $url $group"); ZM\Info("Have the following line data $name $url $group");
$url_bits = null; $url_bits = null;
if ( preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $url) ) { if ( preg_match('/(\d+)\.(\d+)\.(\d+)\.(\d+)/', $url) ) {
@ -183,7 +183,7 @@ if ( 0 ) {
$url_bits = parse_url( $url ); $url_bits = parse_url( $url );
} }
if ( ! $url_bits ) { if ( ! $url_bits ) {
Info("Bad url, skipping line $name $url $group"); ZM\Info("Bad url, skipping line $name $url $group");
continue; continue;
} }
@ -207,11 +207,11 @@ if ( 0 ) {
} // end case import } // end case import
default: default:
{ {
Warning("unknown action " . $_REQUEST['action'] ); ZM\Warning("unknown action " . $_REQUEST['action'] );
} // end ddcase default } // end ddcase default
} }
} else { } else {
Warning("Cannot edit monitors" ); ZM\Warning("Cannot edit monitors" );
} }
ajaxError( 'Unrecognised action or insufficient permissions' ); ajaxError( 'Unrecognised action or insufficient permissions' );

View File

@ -1,6 +1,6 @@
<?php <?php
define("MSG_TIMEOUT", 2.0); define('MSG_TIMEOUT', 2.0);
define("MSG_DATA_SIZE", 4+256); define('MSG_DATA_SIZE', 4+256);
if ( canEdit('Monitors') ) { if ( canEdit('Monitors') ) {
$zmuCommand = getZmuCommand(' -m '.validInt($_REQUEST['id'])); $zmuCommand = getZmuCommand(' -m '.validInt($_REQUEST['id']));

View File

@ -1,5 +1,4 @@
<?php <?php
if ( canEdit('Monitors') ) { if ( canEdit('Monitors') ) {
switch ( $_REQUEST['action'] ) { switch ( $_REQUEST['action'] ) {
case 'sort' : case 'sort' :
@ -25,13 +24,12 @@ if ( canEdit( 'Monitors' ) ) {
} // end case sort } // end case sort
default: default:
{ {
Warning("unknown action " . $_REQUEST['action'] ); ZM\Warning('unknown action ' . $_REQUEST['action']);
} // end ddcase default } // end ddcase default
} }
} else { } else {
Warning("Cannot edit monitors" ); ZM\Warning('Cannot edit monitors');
} }
ajaxError('Unrecognised action or insufficient permissions'); ajaxError('Unrecognised action or insufficient permissions');
?> ?>

View File

@ -8,7 +8,7 @@ if ( empty($_REQUEST['id']) )
if ( canView( 'Control', $_REQUEST['id'] ) ) if ( canView( 'Control', $_REQUEST['id'] ) )
{ {
$monitor = new Monitor( $_REQUEST['id'] ); $monitor = new ZM\Monitor( $_REQUEST['id'] );
$ctrlCommand = buildControlCommand( $monitor ); $ctrlCommand = buildControlCommand( $monitor );

View File

@ -71,7 +71,7 @@ if ( canView( 'Events' ) ) {
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id']; $exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
if ( $exportFile = exportEvents( $exportIds, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat ) ) if ( $exportFile = exportEvents( $exportIds, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat ) )
ajaxResponse( array( 'exportFile'=>$exportFile ) ); ajaxResponse( array( 'exportFormat'=>$exportFormat ) );
else else
ajaxError( 'Export Failed' ); ajaxError( 'Export Failed' );
break; break;
@ -84,7 +84,7 @@ if ( canView( 'Events' ) ) {
$exportStructure = 'flat'; $exportStructure = 'flat';
$exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id']; $exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id'];
if ( $exportFile = exportEvents( $exportIds, false, false, false, $exportVideo, false, $exportFormat, $exportStructure ) ) if ( $exportFile = exportEvents( $exportIds, false, false, false, $exportVideo, false, $exportFormat, $exportStructure ) )
ajaxResponse( array( 'exportFile'=>$exportFile ) ); ajaxResponse( array( 'exportFormat'=>$exportFormat ) );
else else
ajaxError( 'Export Failed' ); ajaxError( 'Export Failed' );
break; break;
@ -119,7 +119,7 @@ if ( canEdit( 'Events' ) ) {
} }
case 'delete' : case 'delete' :
{ {
$Event = new Event( $_REQUEST['id'] ); $Event = new ZM\Event( $_REQUEST['id'] );
if ( ! $Event->Id() ) { if ( ! $Event->Id() ) {
ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.' ) ); ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true, 'message'=> 'Event not found.' ) );
} else { } else {

View File

@ -9,21 +9,21 @@ switch ( $_REQUEST['task'] ) {
{ {
// Silently ignore bogus requests // Silently ignore bogus requests
if ( !empty($_POST['level']) && !empty($_POST['message']) ) { if ( !empty($_POST['level']) && !empty($_POST['message']) ) {
logInit(array('id'=>'web_js')); ZM\logInit(array('id'=>'web_js'));
$string = $_POST['message']; $string = $_POST['message'];
$file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : ''; $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : '';
if ( !empty( $_POST['line'] ) ) if ( !empty( $_POST['line'] ) )
$line = $_POST['line']; $line = validInt($_POST['line']);
else else
$line = NULL; $line = NULL;
$levels = array_flip(Logger::$codes); $levels = array_flip(Logger::$codes);
if ( !isset($levels[$_POST['level']]) ) if ( !isset($levels[$_POST['level']]) )
Panic("Unexpected logger level '".$_POST['level']."'"); ZM\Panic("Unexpected logger level '".$_POST['level']."'");
$level = $levels[$_POST['level']]; $level = $levels[$_POST['level']];
Logger::fetch()->logPrint($level, $string, $file, $line); ZM\Logger::fetch()->logPrint($level, $string, $file, $line);
} }
ajaxResponse(); ajaxResponse();
break; break;
@ -33,7 +33,7 @@ switch ( $_REQUEST['task'] ) {
if ( !canView('System') ) if ( !canView('System') )
ajaxError('Insufficient permissions to view log entries'); ajaxError('Insufficient permissions to view log entries');
$servers = Server::find(); $servers = ZM\Server::find();
$servers_by_Id = array(); $servers_by_Id = array();
# There is probably a better way to do this. # There is probably a better way to do this.
foreach ( $servers as $server ) { foreach ( $servers as $server ) {
@ -46,7 +46,7 @@ switch ( $_REQUEST['task'] ) {
$limit = 100; $limit = 100;
if ( isset($_REQUEST['limit']) ) { if ( isset($_REQUEST['limit']) ) {
if ( ( !is_integer($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) { if ( ( !is_integer($_REQUEST['limit']) and !ctype_digit($_REQUEST['limit']) ) ) {
Error('Invalid value for limit ' . $_REQUEST['limit']); ZM\Error('Invalid value for limit ' . $_REQUEST['limit']);
} else { } else {
$limit = $_REQUEST['limit']; $limit = $_REQUEST['limit'];
} }
@ -54,7 +54,7 @@ switch ( $_REQUEST['task'] ) {
$sortField = 'TimeKey'; $sortField = 'TimeKey';
if ( isset($_REQUEST['sortField']) ) { if ( isset($_REQUEST['sortField']) ) {
if ( !in_array($_REQUEST['sortField'], $filterFields) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) { if ( !in_array($_REQUEST['sortField'], $filterFields) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) {
Error("Invalid sort field " . $_REQUEST['sortField']); ZM\Error("Invalid sort field " . $_REQUEST['sortField']);
} else { } else {
$sortField = $_REQUEST['sortField']; $sortField = $_REQUEST['sortField'];
} }
@ -76,7 +76,7 @@ switch ( $_REQUEST['task'] ) {
foreach ( $filter as $field=>$value ) { foreach ( $filter as $field=>$value ) {
if ( ! in_array($field, $filterFields) ) { if ( ! in_array($field, $filterFields) ) {
Error("$field is not in valid filter fields"); ZM\Error("$field is not in valid filter fields");
continue; continue;
} }
if ( $field == 'Level' ){ if ( $field == 'Level' ){
@ -105,8 +105,8 @@ switch ( $_REQUEST['task'] ) {
$value = $log[$field]; $value = $log[$field];
if ( $field == 'Level' ) { if ( $field == 'Level' ) {
if ( $value <= Logger::INFO ) if ( $value <= ZM\Logger::INFO )
$options[$field][$value] = Logger::$codes[$value]; $options[$field][$value] = ZM\Logger::$codes[$value];
else else
$options[$field][$value] = 'DB'.$value; $options[$field][$value] = 'DB'.$value;
} else if ( $field == 'ServerId' ) { } else if ( $field == 'ServerId' ) {
@ -146,14 +146,14 @@ switch ( $_REQUEST['task'] ) {
$sortField = 'TimeKey'; $sortField = 'TimeKey';
if ( isset($_POST['sortField']) ) { if ( isset($_POST['sortField']) ) {
if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) { if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) {
Error("Invalid sort field " . $_POST['sortField'] ); ZM\Error("Invalid sort field " . $_POST['sortField'] );
} else { } else {
$sortField = $_POST['sortField']; $sortField = $_POST['sortField'];
} }
} }
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc'; $sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
$servers = Server::find(); $servers = ZM\Server::find();
$servers_by_Id = array(); $servers_by_Id = array();
# There is probably a better way to do this. # There is probably a better way to do this.
foreach ( $servers as $server ) { foreach ( $servers as $server ) {
@ -164,11 +164,11 @@ switch ( $_REQUEST['task'] ) {
$where = array(); $where = array();
$values = array(); $values = array();
if ( $minTime ) { if ( $minTime ) {
Logger::Debug("MinTime: $minTime"); ZM\Logger::Debug("MinTime: $minTime");
if ( preg_match('/(.+)(\.\d+)/', $minTime, $matches) ) { if ( preg_match('/(.+)(\.\d+)/', $minTime, $matches) ) {
# This handles sub second precision # This handles sub second precision
$minTime = strtotime($matches[1]).$matches[2]; $minTime = strtotime($matches[1]).$matches[2];
Logger::Debug("MinTime: $minTime"); ZM\Logger::Debug("MinTime: $minTime");
} else { } else {
$minTime = strtotime($minTime); $minTime = strtotime($minTime);
} }
@ -214,27 +214,27 @@ switch ( $_REQUEST['task'] ) {
$exportExt = 'xml'; $exportExt = 'xml';
break; break;
default : default :
Fatal("Unrecognised log export format '$format'"); ZM\Fatal("Unrecognised log export format '$format'");
} }
$exportKey = substr(md5(rand()),0,8); $exportKey = substr(md5(rand()),0,8);
$exportFile = "zm-log.$exportExt"; $exportFile = "zm-log.$exportExt";
if ( ! file_exists(ZM_DIR_EXPORTS) ) { if ( ! file_exists(ZM_DIR_EXPORTS) ) {
Logger::Debug('Creating ' . ZM_DIR_EXPORTS); ZM\Logger::Debug('Creating ' . ZM_DIR_EXPORTS);
if ( ! mkdir(ZM_DIR_EXPORTS) ) { if ( ! mkdir(ZM_DIR_EXPORTS) ) {
Fatal("Can't create exports dir at '".ZM_DIR_EXPORTS."'"); ZM\Fatal("Can't create exports dir at '".ZM_DIR_EXPORTS."'");
} }
} }
$exportPath = ZM_DIR_EXPORTS."/zm-log-$exportKey.$exportExt"; $exportPath = ZM_DIR_EXPORTS."/zm-log-$exportKey.$exportExt";
Logger::Debug("Exporting to $exportPath"); ZM\Logger::Debug("Exporting to $exportPath");
if ( !($exportFP = fopen($exportPath, 'w')) ) if ( !($exportFP = fopen($exportPath, 'w')) )
Fatal("Unable to open log export file $exportPath"); ZM\Fatal("Unable to open log export file $exportPath");
$logs = array(); $logs = array();
foreach ( dbFetchAll($sql, NULL, $values) as $log ) { foreach ( dbFetchAll($sql, NULL, $values) as $log ) {
$log['DateTime'] = preg_replace('/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey']); $log['DateTime'] = preg_replace('/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey']);
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
$logs[] = $log; $logs[] = $log;
} }
Logger::Debug(count($logs)." lines being exported by $sql " . implode(',',$values)); ZM\Logger::Debug(count($logs)." lines being exported by $sql " . implode(',',$values));
switch( $format ) { switch( $format ) {
case 'text' : case 'text' :
@ -318,10 +318,10 @@ switch ( $_REQUEST['task'] ) {
' ); ' );
foreach ( $logs as $log ) { foreach ( $logs as $log ) {
$classLevel = $log['Level']; $classLevel = $log['Level'];
if ( $classLevel < Logger::FATAL ) if ( $classLevel < ZM\Logger::FATAL )
$classLevel = Logger::FATAL; $classLevel = ZM\Logger::FATAL;
elseif ( $classLevel > Logger::DEBUG ) elseif ( $classLevel > ZM\Logger::DEBUG )
$classLevel = Logger::DEBUG; $classLevel = ZM\Logger::DEBUG;
$logClass = 'log-'.strtolower(Logger::$codes[$classLevel]); $logClass = 'log-'.strtolower(Logger::$codes[$classLevel]);
fprintf( $exportFP, " <tr class=\"%s\"><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); fprintf( $exportFP, " <tr class=\"%s\"><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] );
} }
@ -384,10 +384,10 @@ switch ( $_REQUEST['task'] ) {
ajaxError('Insufficient permissions to download logs'); ajaxError('Insufficient permissions to download logs');
if ( empty($_REQUEST['key']) ) if ( empty($_REQUEST['key']) )
Fatal('No log export key given'); ZM\Fatal('No log export key given');
$exportKey = $_REQUEST['key']; $exportKey = $_REQUEST['key'];
if ( empty($_REQUEST['format']) ) if ( empty($_REQUEST['format']) )
Fatal('No log export format given'); ZM\Fatal('No log export format given');
$format = $_REQUEST['format']; $format = $_REQUEST['format'];
switch( $format ) { switch( $format ) {
@ -404,7 +404,7 @@ switch ( $_REQUEST['task'] ) {
$exportExt = 'xml'; $exportExt = 'xml';
break; break;
default : default :
Fatal("Unrecognised log export format '$format'"); ZM\Fatal("Unrecognised log export format '$format'");
} }
$exportFile = "zm-log.$exportExt"; $exportFile = "zm-log.$exportExt";

View File

@ -284,7 +284,7 @@ function collectData() {
if ( in_array($matches[1], $fieldSql) ) { if ( in_array($matches[1], $fieldSql) ) {
$sql .= $matches[1]; $sql .= $matches[1];
} else { } else {
Error('Sort field ' . $matches[1] . ' not in SQL Fields'); ZM\Error('Sort field ' . $matches[1] . ' not in SQL Fields');
} }
if ( count($matches) > 2 ) { if ( count($matches) > 2 ) {
$sql .= ' '.strtoupper($matches[2]); $sql .= ' '.strtoupper($matches[2]);
@ -292,7 +292,7 @@ function collectData() {
$sql .= ' '.strtoupper($matches[3]); $sql .= ' '.strtoupper($matches[3]);
} }
} else { } else {
Error("Sort field didn't match regexp $sort_field"); ZM\Error("Sort field didn't match regexp $sort_field");
} }
} # end foreach sort field } # end foreach sort field
} # end if has sort } # end if has sort
@ -323,7 +323,7 @@ function collectData() {
} }
} }
} }
#Logger::Debug(print_r($data, true)); #ZM\Logger::Debug(print_r($data, true));
return $data; return $data;
} }

View File

@ -20,7 +20,7 @@ if ( sem_acquire($semaphore,1) !== false ) {
$localSocketFile = ZM_PATH_SOCKS.'/zms-'.sprintf('%06d',$_REQUEST['connkey']).'w.sock'; $localSocketFile = ZM_PATH_SOCKS.'/zms-'.sprintf('%06d',$_REQUEST['connkey']).'w.sock';
if ( file_exists( $localSocketFile ) ) { if ( file_exists( $localSocketFile ) ) {
Warning("sock file $localSocketFile already exists?! Is someone else talking to zms?"); ZM\Warning("sock file $localSocketFile already exists?! Is someone else talking to zms?");
// They could be. We can maybe have concurrent requests from a browser. // They could be. We can maybe have concurrent requests from a browser.
} }
if ( ! socket_bind( $socket, $localSocketFile ) ) { if ( ! socket_bind( $socket, $localSocketFile ) ) {
@ -29,23 +29,23 @@ if ( sem_acquire($semaphore,1) !== false ) {
switch ( $_REQUEST['command'] ) { switch ( $_REQUEST['command'] ) {
case CMD_VARPLAY : case CMD_VARPLAY :
Logger::Debug( 'Varplaying to '.$_REQUEST['rate'] ); ZM\Logger::Debug( 'Varplaying to '.$_REQUEST['rate'] );
$msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 ); $msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['rate']+32768 );
break; break;
case CMD_ZOOMIN : case CMD_ZOOMIN :
Logger::Debug( 'Zooming to '.$_REQUEST['x'].",".$_REQUEST['y'] ); ZM\Logger::Debug( 'Zooming to '.$_REQUEST['x'].",".$_REQUEST['y'] );
$msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] ); $msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
break; break;
case CMD_PAN : case CMD_PAN :
Logger::Debug( 'Panning to '.$_REQUEST['x'].",".$_REQUEST['y'] ); ZM\Logger::Debug( 'Panning to '.$_REQUEST['x'].",".$_REQUEST['y'] );
$msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] ); $msg = pack( 'lcnn', MSG_CMD, $_REQUEST['command'], $_REQUEST['x'], $_REQUEST['y'] );
break; break;
case CMD_SCALE : case CMD_SCALE :
Logger::Debug( 'Scaling to '.$_REQUEST['scale'] ); ZM\Logger::Debug( 'Scaling to '.$_REQUEST['scale'] );
$msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] ); $msg = pack( 'lcn', MSG_CMD, $_REQUEST['command'], $_REQUEST['scale'] );
break; break;
case CMD_SEEK : case CMD_SEEK :
Logger::Debug( 'Seeking to '.$_REQUEST['offset'] ); ZM\Logger::Debug( 'Seeking to '.$_REQUEST['offset'] );
$msg = pack( 'lcN', MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] ); $msg = pack( 'lcN', MSG_CMD, $_REQUEST['command'], $_REQUEST['offset'] );
break; break;
default : default :
@ -81,18 +81,18 @@ if ( sem_acquire($semaphore,1) !== false ) {
$numSockets = socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 ); $numSockets = socket_select( $rSockets, $wSockets, $eSockets, intval($timeout/1000), ($timeout%1000)*1000 );
if ( $numSockets === false ) { if ( $numSockets === false ) {
Error('socket_select failed: ' . socket_strerror(socket_last_error()) ); ZM\Error('socket_select failed: ' . socket_strerror(socket_last_error()) );
ajaxError( 'socket_select failed: '.socket_strerror(socket_last_error()) ); ajaxError( 'socket_select failed: '.socket_strerror(socket_last_error()) );
} else if ( $numSockets < 0 ) { } else if ( $numSockets < 0 ) {
Error( "Socket closed $remSockFile" ); ZM\Error( "Socket closed $remSockFile" );
ajaxError( "Socket closed $remSockFile" ); ajaxError( "Socket closed $remSockFile" );
} else if ( $numSockets == 0 ) { } else if ( $numSockets == 0 ) {
Error( "Timed out waiting for msg $remSockFile" ); ZM\Error( "Timed out waiting for msg $remSockFile" );
socket_Set_nonblock($socket); socket_Set_nonblock($socket);
#ajaxError( "Timed out waiting for msg $remSockFile" ); #ajaxError( "Timed out waiting for msg $remSockFile" );
} else if ( $numSockets > 0 ) { } else if ( $numSockets > 0 ) {
if ( count($rSockets) != 1 ) { if ( count($rSockets) != 1 ) {
Error( 'Bogus return from select, '.count($rSockets).' sockets available' ); ZM\Error( 'Bogus return from select, '.count($rSockets).' sockets available' );
ajaxError( 'Bogus return from select, '.count($rSockets).' sockets available' ); ajaxError( 'Bogus return from select, '.count($rSockets).' sockets available' );
} }
} }
@ -122,9 +122,9 @@ if ( sem_acquire($semaphore,1) !== false ) {
case MSG_DATA_WATCH : case MSG_DATA_WATCH :
{ {
$data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg ); $data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg );
Logger::Debug("FPS: " . $data['fps'] ); ZM\Logger::Debug("FPS: " . $data['fps'] );
$data['fps'] = round( $data['fps'], 2 ); $data['fps'] = round( $data['fps'], 2 );
Logger::Debug("FPS: " . $data['fps'] ); ZM\Logger::Debug("FPS: " . $data['fps'] );
$data['rate'] /= RATE_BASE; $data['rate'] /= RATE_BASE;
$data['delay'] = round( $data['delay'], 2 ); $data['delay'] = round( $data['delay'], 2 );
$data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 ); $data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 );
@ -161,7 +161,7 @@ if ( sem_acquire($semaphore,1) !== false ) {
} }
sem_release($semaphore); sem_release($semaphore);
} else { } else {
Logger::Debug("Couldn't get semaphore"); ZM\Logger::Debug("Couldn't get semaphore");
ajaxResponse( array() ); ajaxResponse( array() );
} }

View File

@ -120,7 +120,7 @@ Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@');
Configure::write('ZM_VERSION', '@VERSION@'); Configure::write('ZM_VERSION', '@VERSION@');
Configure::write('ZM_API_VERSION', '@API_VERSION@'); Configure::write('ZM_API_VERSION', '@API_VERSION@');
require_once("../../../includes/config.php"); require_once(__DIR__ ."/../../../includes/config.php");
global $configvals; global $configvals;
# Now that our array our finalized, and the config has been defined. # Now that our array our finalized, and the config has been defined.

View File

@ -70,7 +70,7 @@ class AppController extends Controller {
$user = $this->Session->read('user'); $user = $this->Session->read('user');
if ( ZM_OPT_USE_AUTH ) { if ( ZM_OPT_USE_AUTH ) {
require_once '../../../includes/auth.php'; require_once __DIR__ .'/../../../includes/auth.php';
$mUser = $this->request->query('user') ? $this->request->query('user') : $this->request->data('user'); $mUser = $this->request->query('user') ? $this->request->query('user') : $this->request->data('user');
$mPassword = $this->request->query('pass') ? $this->request->query('pass') : $this->request->data('pass'); $mPassword = $this->request->query('pass') ? $this->request->query('pass') : $this->request->data('pass');

View File

@ -66,7 +66,7 @@ class HostController extends AppController {
if ( $isZmAuth ) { if ( $isZmAuth ) {
// In future, we may want to completely move to AUTH_HASH_LOGINS and return &auth= for all cases // In future, we may want to completely move to AUTH_HASH_LOGINS and return &auth= for all cases
require_once "../../../includes/auth.php"; # in the event we directly call getCredentials.json require_once __DIR__ .'/../../../includes/auth.php'; # in the event we directly call getCredentials.json
$this->Session->read('user'); # this is needed for command line/curl to recognize a session $this->Session->read('user'); # this is needed for command line/curl to recognize a session
$zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value']; $zmAuthRelay = $this->Config->find('first',array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_AUTH_RELAY')))['Config']['Value'];
if ( $zmAuthRelay == 'hashed' ) { if ( $zmAuthRelay == 'hashed' ) {

View File

@ -1,4 +1,5 @@
<?php <?php
namespace ZM;
$event_cache = array(); $event_cache = array();

View File

@ -1,4 +1,5 @@
<?php <?php
namespace ZM;
class Filter { class Filter {
@ -186,6 +187,60 @@ public $defaults = array(
} }
} }
} # end function set } # end function set
public function control($command, $server_id=null) {
$Servers = $server_id ? Server::find(array('Id'=>$server_id)) : Server::find();
if ( !count($Servers) and !$server_id ) {
# This will be the non-multi-server case
$Servers = array(new Server());
}
foreach ( $Servers as $Server ) {
if ( !defined('ZM_SERVER_ID') or !$Server->Id() or ZM_SERVER_ID==$Server->Id() ) {
# Local
Logger::Debug("Controlling filter locally $command for server ".$Server->Id());
daemonControl($command, 'zmfilter.pl', '--filter_id='.$this->{'Id'});
} else {
# Remote case
$url = $Server->UrlToIndex();
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == 'hashed' ) {
$url .= '?auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
} else if ( ZM_AUTH_RELAY == 'plain' ) {
$url = '?user='.$_SESSION['username'];
$url = '?pass='.$_SESSION['password'];
} else if ( ZM_AUTH_RELAY == 'none' ) {
$url = '?user='.$_SESSION['username'];
}
}
$url .= '&view=filter&action=control&command='.$command.'&Id='.$this->Id().'&ServerId'.$Server->Id();
Logger::Debug("sending command to $url");
$data = array();
if ( defined('ZM_ENABLE_CSRF_MAGIC') )
$data['__csrf_magic'] = csrf_get_secret();
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
try {
$result = file_get_contents($url, false, $context);
if ( $result === FALSE ) { /* Handle error */
Error("Error restarting zmfilter.pl using $url");
}
} catch ( Exception $e ) {
Error("Except $e thrown trying to restart zmfilter");
}
} # end if local or remote
} # end foreach erver
} # end function control
} # end class Filter } # end class Filter
?> ?>

View File

@ -1,4 +1,5 @@
<?php <?php
namespace ZM;
require_once( 'database.php' ); require_once( 'database.php' );
require_once( 'Event.php' ); require_once( 'Event.php' );
@ -50,9 +51,8 @@ class Frame {
} }
public function getImageSrc( $show='capture' ) { public function getImageSrc( $show='capture' ) {
return '?view=image&fid='.$this->{'FrameId'}.'&eid='.$this->{'EventId'}.'&show='.$show;
return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'FrameId'}.'&eid='.$this->{'EventId'}.'&show='.$show; #return '?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg';
#return $_SERVER['PHP_SELF'].'?view=image&fid='.$this->{'Id'}.'&show='.$show.'&filename='.$this->Event()->MonitorId().'_'.$this->{'EventId'}.'_'.$this->{'FrameId'}.'.jpg';
} // end function getImageSrc } // end function getImageSrc
public static function find( $parameters = array(), $options = NULL ) { public static function find( $parameters = array(), $options = NULL ) {

View File

@ -1,4 +1,5 @@
<?php <?php
namespace ZM;
$group_cache = array(); $group_cache = array();

View File

@ -1,4 +1,5 @@
<?php <?php
namespace ZM;
require_once('database.php'); require_once('database.php');
require_once('Server.php'); require_once('Server.php');
@ -331,6 +332,20 @@ private $control_fields = array(
return $this->defaults{$field}; return $this->defaults{$field};
} // end function Height } // end function Height
public function SignalCheckColour($new=null) {
$field = 'SignalCheckColour';
if ($new) {
$this->{$field} = $new;
}
// Validate that it's a valid colour (we seem to allow color names, not just hex).
// This also helps prevent XSS.
if (array_key_exists($field, $this) && preg_match('/^[#0-9a-zA-Z]+$/', $this->{$field})) {
return $this->{$field};
}
return $this->defaults{$field};
} // end function SignalCheckColour
public function set($data) { public function set($data) {
foreach ($data as $k => $v) { foreach ($data as $k => $v) {
if ( method_exists($this, $k) ) { if ( method_exists($this, $k) ) {

View File

@ -1,4 +1,5 @@
<?php <?php
namespace ZM;
require_once('database.php'); require_once('database.php');
@ -98,9 +99,9 @@ class MontageLayout {
} }
$result = dbQuery($sql, $values); $result = dbQuery($sql, $values);
if ( $result ) { if ( $result ) {
$results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'MontageLayout'); $results = $result->fetchALL();
foreach ( $results as $row => $obj ) { foreach ( $results as $row ) {
$filters[] = $obj; $filters[] = new MontageLayout($row);
} }
} }
return $filters; return $filters;

View File

@ -1,8 +1,10 @@
<?php <?php
namespace ZM;
require_once('database.php'); require_once('database.php');
$server_cache = array(); $server_cache = array();
class Server { class Server {
private $defaults = array( private $defaults = array(
'Id' => null, 'Id' => null,
@ -117,7 +119,8 @@ class Server {
if ( isset($this->{'PathToIndex'}) and $this->{'PathToIndex'} ) { if ( isset($this->{'PathToIndex'}) and $this->{'PathToIndex'} ) {
return $this->{'PathToIndex'}; return $this->{'PathToIndex'};
} }
return $_SERVER['PHP_SELF']; // We can't trust PHP_SELF to not include an XSS vector. See note in skin.js.php.
return preg_replace('/\.php.*$/i', '.php', $_SERVER['PHP_SELF']);
} }
public function UrlToIndex( $port=null ) { public function UrlToIndex( $port=null ) {

View File

@ -1,5 +1,7 @@
<?php <?php
namespace ZM;
require_once('database.php'); require_once('database.php');
require_once('Event.php');
$storage_cache = array(); $storage_cache = array();
class Storage { class Storage {
@ -223,5 +225,19 @@ class Storage {
} }
return $this->{'Server'}; return $this->{'Server'};
} }
public function to_json() {
$json = array();
foreach ($this->defaults as $key => $value) {
if ( is_callable(array($this, $key)) ) {
$json[$key] = $this->$key();
} else if ( array_key_exists($key, $this) ) {
$json[$key] = $this->{$key};
} else {
$json[$key] = $this->defaults{$key};
}
}
return json_encode($json);
}
} }
?> ?>

View File

@ -23,5 +23,6 @@ if ( $action == 'bandwidth' && isset($_REQUEST['newBandwidth']) ) {
$_COOKIE['zmBandwidth'] = validStr($_REQUEST['newBandwidth']); $_COOKIE['zmBandwidth'] = validStr($_REQUEST['newBandwidth']);
setcookie('zmBandwidth', validStr($_REQUEST['newBandwidth']), time()+3600*24*30*12*10); setcookie('zmBandwidth', validStr($_REQUEST['newBandwidth']), time()+3600*24*30*12*10);
$refreshParent = true; $refreshParent = true;
$view = 'none';
} }
?> ?>

View File

@ -20,7 +20,7 @@
if ( $action == 'delete' ) { if ( $action == 'delete' ) {
if ( ! canEdit('Monitors') ) { if ( ! canEdit('Monitors') ) {
Warning("No permission to delete monitors"); ZM\Warning('No permission to delete monitors');
return; return;
} }
@ -30,7 +30,7 @@ if ( $action == 'delete' ) {
if ( canEdit('Monitors', $markMid) ) { if ( canEdit('Monitors', $markMid) ) {
// This could be faster as a select all // This could be faster as a select all
if ( $monitor = dbFetchOne('SELECT * FROM Monitors WHERE Id = ?', NULL, array($markMid)) ) { if ( $monitor = dbFetchOne('SELECT * FROM Monitors WHERE Id = ?', NULL, array($markMid)) ) {
$Monitor = new Monitor($monitor); $Monitor = new ZM\Monitor($monitor);
$Monitor->delete(); $Monitor->delete();
} // end if monitor found in db } // end if monitor found in db
} // end if canedit this monitor } // end if canedit this monitor

View File

@ -20,11 +20,11 @@
// Monitor control actions, require a monitor id and control view permissions for that monitor // Monitor control actions, require a monitor id and control view permissions for that monitor
if ( empty($_REQUEST['mid']) ) { if ( empty($_REQUEST['mid']) ) {
Warning("Settings requires a monitor id"); ZM\Warning('Settings requires a monitor id');
return; return;
} }
if ( ! canView('Control', $_REQUEST['mid']) ) { if ( ! canView('Control', $_REQUEST['mid']) ) {
Warning("Settings requires the Control permission"); ZM\Warning('Settings requires the Control permission');
return; return;
} }
@ -32,7 +32,7 @@ require_once('control_functions.php');
require_once('Monitor.php'); require_once('Monitor.php');
$mid = validInt($_REQUEST['mid']); $mid = validInt($_REQUEST['mid']);
if ( $action == 'control' ) { if ( $action == 'control' ) {
$monitor = new Monitor($mid); $monitor = new ZM\Monitor($mid);
$ctrlCommand = buildControlCommand($monitor); $ctrlCommand = buildControlCommand($monitor);
sendControlCommand($monitor->Id(), $ctrlCommand); sendControlCommand($monitor->Id(), $ctrlCommand);

View File

@ -20,13 +20,13 @@
if ( !canEdit('Control') ) { if ( !canEdit('Control') ) {
Warning("Need Control permissions to edit control capabilities"); ZM\Warning('Need Control permissions to edit control capabilities');
return; return;
} // end if !canEdit Controls } // end if !canEdit Controls
if ( $action == 'controlcap' ) { if ( $action == 'controlcap' ) {
require_once('Control.php'); require_once('includes/Control.php');
$Control = new Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null ); $Control = new ZM\Control( !empty($_REQUEST['cid']) ? $_REQUEST['cid'] : null );
//$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns ); //$changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns );
$Control->save($_REQUEST['newControl']); $Control->save($_REQUEST['newControl']);

View File

@ -20,16 +20,15 @@
if ( !canEdit('Control') ) { if ( !canEdit('Control') ) {
Warning("Need Control permissions to edit control capabilities"); ZM\Warning('Need Control permissions to edit control capabilities');
return; return;
} // end if !canEdit Controls } // end if !canEdit Controls
}
if ( $action == 'delete' ) { if ( $action == 'delete' ) {
if ( isset($_REQUEST['markCids']) ) { if ( isset($_REQUEST['markCids']) ) {
foreach( $_REQUEST['markCids'] as $markCid ) { foreach( $_REQUEST['markCids'] as $markCid ) {
dbQuery('DELETE FROM Controls WHERE Id = ?', array($markCid));
dbQuery('UPDATE Monitors SET Controllable = 0, ControlId = 0 WHERE ControlId = ?', array($markCid)); dbQuery('UPDATE Monitors SET Controllable = 0, ControlId = 0 WHERE ControlId = ?', array($markCid));
dbQuery('DELETE FROM Controls WHERE Id = ?', array($markCid));
$refreshParent = true; $refreshParent = true;
} }
} }

View File

@ -20,7 +20,7 @@
// Device view actions // Device view actions
if ( !canEdit('Devices') ) { if ( !canEdit('Devices') ) {
Warning("No devices permission in editing device"); ZM\Warning('No devices permission in editing device');
return; return;
} // end if !canEdit(Devices) } // end if !canEdit(Devices)
@ -39,7 +39,7 @@ if ( $action == 'device' ) {
$view = 'none'; $view = 'none';
} }
} else { } else {
Error("Unknown action in device"); ZM\Error('Unknown action in device');
} // end if action } // end if action
?> ?>

View File

@ -20,7 +20,7 @@
// Device view actions // Device view actions
if ( !canEdit('Devices') ) { if ( !canEdit('Devices') ) {
Warning("No devices permission in editing device"); ZM\Warning('No devices permission in editing device');
return; return;
} // end if !canEdit(Devices) } // end if !canEdit(Devices)

View File

@ -19,7 +19,7 @@
// //
if ( !canEdit('System') ) { if ( !canEdit('System') ) {
Warning("Need System permissions to update donation"); ZM\Warning('Need System permissions to update donation');
return; return;
} }

View File

@ -20,7 +20,7 @@
// If there is an action on an event, then we must have an id. // If there is an action on an event, then we must have an id.
if ( !empty($_REQUEST['eid']) ) { if ( !empty($_REQUEST['eid']) ) {
Warning("No eid in action on event view"); ZM\Warning('No eid in action on event view');
return; return;
} }

View File

@ -19,13 +19,13 @@
// //
if ( !isset($_REQUEST['markEids']) ) { if ( !isset($_REQUEST['markEids']) ) {
Warning('Events actions require eids'); ZM\Warning('Events actions require eids');
return; return;
} }
// Event scope actions, view permissions only required // Event scope actions, view permissions only required
if ( !canEdit('Events') ) { if ( !canEdit('Events') ) {
Warning("Events actions require Edit permissions"); ZM\Warning('Events actions require Edit permissions');
return; return;
} // end if ! canEdit(Events) } // end if ! canEdit(Events)

View File

@ -19,13 +19,13 @@
// //
if ( !isset($_REQUEST['markEids']) ) { if ( !isset($_REQUEST['markEids']) ) {
Warning('Events actions require eids'); ZM\Warning('Events actions require eids');
return; return;
} }
// Event scope actions, view permissions only required // Event scope actions, view permissions only required
if ( !canEdit('Events') ) { if ( !canEdit('Events') ) {
Warning("Events actions require Edit permissions"); ZM\Warning('Events actions require Edit permissions');
return; return;
} // end if ! canEdit(Events) } // end if ! canEdit(Events)

View File

@ -20,7 +20,7 @@
// Event scope actions, view permissions only required // Event scope actions, view permissions only required
if ( !canView('Events') ) { if ( !canView('Events') ) {
Warning('You do not have permission to view Events.'); ZM\Warning('You do not have permission to view Events.');
return; return;
} }
@ -30,9 +30,19 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
} elseif ( $action == 'delterm' ) { } elseif ( $action == 'delterm' ) {
$_REQUEST['filter'] = delFilterTerm($_REQUEST['filter'], $_REQUEST['line']); $_REQUEST['filter'] = delFilterTerm($_REQUEST['filter'], $_REQUEST['line']);
} else if ( canEdit('Events') ) { } else if ( canEdit('Events') ) {
require_once('includes/Filter.php');
$filter = new ZM\Filter($_REQUEST['Id']);
if ( $action == 'delete' ) { if ( $action == 'delete' ) {
if ( !empty($_REQUEST['Id']) ) { if ( !empty($_REQUEST['Id']) ) {
dbQuery('DELETE FROM Filters WHERE Id=?', array($_REQUEST['Id'])); if ( $filter->Background() ) {
$filter->control('stop');
}
$filter->delete();
} else {
ZM\Error("No filter id passed when deleting");
} }
} else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) { } else if ( ( $action == 'Save' ) or ( $action == 'SaveAs' ) or ( $action == 'execute' ) ) {
@ -66,15 +76,30 @@ if ( isset($_REQUEST['object']) and ( $_REQUEST['object'] == 'filter' ) ) {
if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) { if ( $_REQUEST['Id'] and ( $action == 'Save' ) ) {
dbQuery('UPDATE Filters SET '.$sql.' WHERE Id=?', array($_REQUEST['Id'])); dbQuery('UPDATE Filters SET '.$sql.' WHERE Id=?', array($_REQUEST['Id']));
if ( $filter->Background() )
$filter->control('stop');
} else { } else {
dbQuery('INSERT INTO Filters SET'.$sql); dbQuery('INSERT INTO Filters SET'.$sql);
$_REQUEST['Id'] = dbInsertId(); $_REQUEST['Id'] = dbInsertId();
$filter = new Filter($_REQUEST['Id']);
} }
if ( !empty($_REQUEST['filter']['Background']) )
$filter->control('start');
if ( $action == 'execute' ) { if ( $action == 'execute' ) {
executeFilter($_REQUEST['Id']); executeFilter($_REQUEST['Id']);
$view = 'events'; $view = 'events';
} }
} else if ( $action == 'control' ) {
if ( $_REQUEST['command'] == 'start'
or $_REQUEST['command'] == 'stop'
or $_REQUEST['command'] == 'restart'
) {
$filter->control($_REQUEST['command'], $_REQUEST['ServerId']);
} else {
ZM\Error('Invalid command for filter ('.$_REQUEST['command'].')');
}
} // end if save or execute } // end if save or execute
} // end if canEdit(Events) } // end if canEdit(Events)
} // end if object == filter } // end if object == filter

View File

@ -21,12 +21,12 @@
// Monitor edit actions, require a monitor id and edit permissions for that monitor // Monitor edit actions, require a monitor id and edit permissions for that monitor
if ( empty($_REQUEST['mid']) ) { if ( empty($_REQUEST['mid']) ) {
Error("Must specify mid"); ZM\Error('Must specify mid');
return; return;
} }
$mid = validInt($_REQUEST['mid']); $mid = validInt($_REQUEST['mid']);
if ( !canEdit('Monitors', $mid) ) { if ( !canEdit('Monitors', $mid) ) {
Error("You do not have permission to edit monitor $mid"); ZM\Error("You do not have permission to edit monitor $mid");
return; return;
} }
@ -52,7 +52,7 @@ if ( $action == 'function' ) {
} }
$refreshParent = true; $refreshParent = true;
} else { } else {
Logger::Debug("No change to function, not doing anything."); ZM\Logger::Debug('No change to function, not doing anything.');
} }
} // end if action } // end if action
$view = 'none'; $view = 'none';

View File

@ -22,7 +22,7 @@
# Should probably verify that each monitor id is a valid monitor, that we have access to. # Should probably verify that each monitor id is a valid monitor, that we have access to.
# However at the moment, you have to have System permissions to do this # However at the moment, you have to have System permissions to do this
if ( ! canEdit('Groups') ) { if ( ! canEdit('Groups') ) {
Warning("Need group edit permissions to edit groups"); ZM\Warning('Need group edit permissions to edit groups');
return; return;
} }

View File

@ -33,17 +33,17 @@ if ( ($action == 'setgroup') && canView('Groups')) {
# Should probably verify that each monitor id is a valid monitor, that we have access to. # Should probably verify that each monitor id is a valid monitor, that we have access to.
# However at the moment, you have to have System permissions to do this # However at the moment, you have to have System permissions to do this
if ( ! canEdit('Groups') ) { if ( ! canEdit('Groups') ) {
Warning("Need group edit permissions to edit groups"); ZM\Warning('Need group edit permissions to edit groups');
return; return;
} }
if ( $action == 'delete' ) { if ( $action == 'delete' ) {
if ( !empty($_REQUEST['gid']) ) { if ( !empty($_REQUEST['gid']) ) {
foreach ( Group::find(array('Id'=>$_REQUEST['gid'])) as $Group ) { foreach ( ZM\Group::find(array('Id'=>$_REQUEST['gid'])) as $Group ) {
$Group->delete(); $Group->delete();
} }
} }
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=groups'; $redirect = '?view=groups';
$refreshParent = true; $refreshParent = true;
} # end if action } # end if action
?> ?>

View File

@ -25,10 +25,10 @@ if ( isset($_REQUEST['object']) and $_REQUEST['object'] == 'Monitor' ) {
foreach ( $_REQUEST['mids'] as $mid ) { foreach ( $_REQUEST['mids'] as $mid ) {
$mid = ValidInt($mid); $mid = ValidInt($mid);
if ( ! canEdit('Monitors', $mid) ) { if ( ! canEdit('Monitors', $mid) ) {
Warning("Cannot edit monitor $mid"); ZM\Warning("Cannot edit monitor $mid");
continue; continue;
} }
$Monitor = new Monitor($mid); $Monitor = new ZM\Monitor($mid);
if ( $Monitor->Type() != 'WebSite' ) { if ( $Monitor->Type() != 'WebSite' ) {
$Monitor->zmaControl('stop'); $Monitor->zmaControl('stop');
$Monitor->zmcControl('stop'); $Monitor->zmcControl('stop');
@ -47,7 +47,7 @@ if ( isset($_REQUEST['object']) and $_REQUEST['object'] == 'Monitor' ) {
// Monitor edit actions, monitor id derived, require edit permissions for that monitor // Monitor edit actions, monitor id derived, require edit permissions for that monitor
if ( ! canEdit('Monitors') ) { if ( ! canEdit('Monitors') ) {
Warning("Monitor actions require Monitors Permissions"); ZM\Warning("Monitor actions require Monitors Permissions");
return; return;
} }
@ -68,7 +68,7 @@ if ( $action == 'monitor' ) {
$x10Monitor = array(); $x10Monitor = array();
} }
} }
$Monitor = new Monitor($monitor); $Monitor = new ZM\Monitor($monitor);
// Define a field type for anything that's not simple text equivalent // Define a field type for anything that's not simple text equivalent
$types = array( $types = array(
@ -86,10 +86,10 @@ if ( $action == 'monitor' ) {
if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) { if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) {
$_REQUEST['newMonitor']['ServerId'] = dbFetchOne( $_REQUEST['newMonitor']['ServerId'] = dbFetchOne(
'SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id'); 'SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem DESC, CpuLoad ASC LIMIT 1', 'Id');
Logger::Debug('Auto selecting server: Got ' . $_REQUEST['newMonitor']['ServerId'] ); ZM\Logger::Debug('Auto selecting server: Got ' . $_REQUEST['newMonitor']['ServerId'] );
if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) { if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) {
$_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID; $_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID;
Logger::Debug('Auto selecting server to ' . ZM_SERVER_ID); ZM\Logger::Debug('Auto selecting server to ' . ZM_SERVER_ID);
} }
} }
@ -107,12 +107,12 @@ if ( $action == 'monitor' ) {
dbQuery('UPDATE Monitors SET '.implode(', ', $changes).' WHERE Id=?', array($mid)); dbQuery('UPDATE Monitors SET '.implode(', ', $changes).' WHERE Id=?', array($mid));
// Groups will be added below // Groups will be added below
if ( isset($changes['Name']) or isset($changes['StorageId']) ) { if ( isset($changes['Name']) or isset($changes['StorageId']) ) {
$OldStorage = new Storage($monitor['StorageId']); $OldStorage = new ZM\Storage($monitor['StorageId']);
$saferOldName = basename($monitor['Name']); $saferOldName = basename($monitor['Name']);
if ( file_exists($OldStorage->Path().'/'.$saferOldName) ) if ( file_exists($OldStorage->Path().'/'.$saferOldName) )
unlink($OldStorage->Path().'/'.$saferOldName); unlink($OldStorage->Path().'/'.$saferOldName);
$NewStorage = new Storage($_REQUEST['newMonitor']['StorageId']); $NewStorage = new ZM\Storage($_REQUEST['newMonitor']['StorageId']);
if ( ! file_exists($NewStorage->Path().'/'.$mid) ) if ( ! file_exists($NewStorage->Path().'/'.$mid) )
mkdir($NewStorage->Path().'/'.$mid, 0755); mkdir($NewStorage->Path().'/'.$mid, 0755);
$saferNewName = basename($_REQUEST['newMonitor']['Name']); $saferNewName = basename($_REQUEST['newMonitor']['Name']);
@ -164,24 +164,24 @@ if ( $action == 'monitor' ) {
$zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height']; $zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height'];
dbQuery("INSERT INTO Zones SET MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) ); dbQuery("INSERT INTO Zones SET MonitorId = ?, Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = ?, Area=?, AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels=?, MaxAlarmPixels=?, FilterX = 3, FilterY = 3, MinFilterPixels=?, MaxFilterPixels=?, MinBlobPixels=?, MinBlobs = 1", array( $mid, sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 ), $zoneArea, intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*3)/100), intval(($zoneArea*75)/100), intval(($zoneArea*2)/100) ) );
//$view = 'none'; //$view = 'none';
$Storage = new Storage($_REQUEST['newMonitor']['StorageId']); $Storage = new ZM\Storage($_REQUEST['newMonitor']['StorageId']);
mkdir($Storage->Path().'/'.$mid, 0755); mkdir($Storage->Path().'/'.$mid, 0755);
$saferName = basename($_REQUEST['newMonitor']['Name']); $saferName = basename($_REQUEST['newMonitor']['Name']);
symlink($mid, $Storage->Path().'/'.$saferName); symlink($mid, $Storage->Path().'/'.$saferName);
} else { } else {
Error('Error saving new Monitor.'); ZM\Error('Error saving new Monitor.');
$error_message = dbError($sql); $error_message = dbError($sql);
return; return;
} }
} else { } else {
Error('Users with Monitors restrictions cannot create new monitors.'); ZM\Error('Users with Monitors restrictions cannot create new monitors.');
return; return;
} }
$restart = true; $restart = true;
} else { } else {
Logger::Debug('No action due to no changes to Monitor'); ZM\Logger::Debug('No action due to no changes to Monitor');
} # end if count(changes) } # end if count(changes)
if ( if (
@ -220,7 +220,7 @@ if ( $action == 'monitor' ) {
if ( $restart ) { if ( $restart ) {
$new_monitor = new Monitor($mid); $new_monitor = new ZM\Monitor($mid);
//fixDevices(); //fixDevices();
if ( $new_monitor->Type() != 'WebSite' ) { if ( $new_monitor->Type() != 'WebSite' ) {
@ -238,6 +238,6 @@ if ( $action == 'monitor' ) {
} // end if restart } // end if restart
$view = 'none'; $view = 'none';
} else { } else {
Warning("Unknown action $action in Monitor"); ZM\Warning("Unknown action $action in Monitor");
} // end if action == Delete } // end if action == Delete
?> ?>

View File

@ -22,7 +22,7 @@ if ( isset($_REQUEST['object']) ) {
if ( $_REQUEST['object'] == 'MontageLayout' ) { if ( $_REQUEST['object'] == 'MontageLayout' ) {
// System edit actions // System edit actions
if ( ! canEdit('System') ) { if ( ! canEdit('System') ) {
Warning("Need System permissions to edit layouts"); ZM\Warning('Need System permissions to edit layouts');
return; return;
} }
require_once('includes/MontageLayout.php'); require_once('includes/MontageLayout.php');
@ -40,7 +40,7 @@ if ( isset($_REQUEST['object']) ) {
$_SESSION['zmMontageLayout'] = $Layout->Id(); $_SESSION['zmMontageLayout'] = $Layout->Id();
setcookie('zmMontageLayout', $Layout->Id(), 1); setcookie('zmMontageLayout', $Layout->Id(), 1);
session_write_close(); session_write_close();
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montage'; $redirect = '?view=montage';
} // end if save } // end if save
} # end if isset($_REQUEST['object'] ) } # end if isset($_REQUEST['object'] )

View File

@ -20,7 +20,7 @@
// System edit actions // System edit actions
if ( !canEdit('System') ) { if ( !canEdit('System') ) {
Warning("Must have System permissions to perform options actions"); ZM\Warning('Must have System permissions to perform options actions');
return; return;
} }
@ -89,7 +89,7 @@ if ( $action == 'delete' ) {
case 'lowband' : case 'lowband' :
break; break;
} }
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=options&tab='.$_REQUEST['tab']; $redirect = '?view=options&tab='.$_REQUEST['tab'];
} }
loadConfig(false); loadConfig(false);
return; return;

View File

@ -19,21 +19,21 @@
// //
if ( !canEdit('System') ) { if ( !canEdit('System') ) {
Warning("Need System permissions to update privacy"); ZM\Warning('Need System permissions to update privacy');
return; return;
} }
if ( ($action == 'privacy') && isset($_REQUEST['option']) ) { if ( ($action == 'privacy') && isset($_POST['option']) ) {
switch( $_REQUEST['option'] ) { switch( $_POST['option'] ) {
case 'decline' : case '0' :
dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'"); dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'");
dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_TELEMETRY_DATA'"); dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_TELEMETRY_DATA'");
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; $redirect = '?view=console';
break; break;
case 'accept' : case '1' :
dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'"); dbQuery("UPDATE Config SET Value = '0' WHERE Name = 'ZM_SHOW_PRIVACY'");
dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_TELEMETRY_DATA'"); dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_TELEMETRY_DATA'");
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; $redirect = '?view=console';
break; break;
default: # Enable the privacy statement if we somehow submit something other than accept or decline default: # Enable the privacy statement if we somehow submit something other than accept or decline
dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_SHOW_PRIVACY'"); dbQuery("UPDATE Config SET Value = '1' WHERE Name = 'ZM_SHOW_PRIVACY'");

View File

@ -20,7 +20,7 @@
// System edit actions // System edit actions
if ( ! canEdit('System') ) { if ( ! canEdit('System') ) {
Warning("Need System permissions to add servers"); ZM\Warning('Need System permissions to add servers');
return; return;
} }
@ -48,6 +48,6 @@ if ( $action == 'Save' ) {
} }
$view = 'none'; $view = 'none';
} else { } else {
Error("Unknown action $action in saving Server"); ZM\Error("Unknown action $action in saving Server");
} }
?> ?>

View File

@ -21,11 +21,11 @@
// Monitor control actions, require a monitor id and control view permissions for that monitor // Monitor control actions, require a monitor id and control view permissions for that monitor
if ( empty($_REQUEST['mid']) ) { if ( empty($_REQUEST['mid']) ) {
Warning("Settings requires a monitor id"); ZM\Warning('Settings requires a monitor id');
return; return;
} }
if ( ! canView('Control', $_REQUEST['mid']) ) { if ( ! canView('Control', $_REQUEST['mid']) ) {
Warning("Settings requires the Control permission"); ZM\Warning('Settings requires the Control permission');
return; return;
} }

View File

@ -20,7 +20,7 @@
// System edit actions // System edit actions
if ( !canEdit('System') ) { if ( !canEdit('System') ) {
Warning('Need System Permission to edit states'); ZM\Warning('Need System Permission to edit states');
return; return;
} }
if ( $action == 'state' ) { if ( $action == 'state' ) {

View File

@ -20,7 +20,7 @@
// System edit actions // System edit actions
if ( ! canEdit('System') ) { if ( ! canEdit('System') ) {
Warning("Need System permission to edit Storage"); ZM\Warning('Need System permission to edit Storage');
return; return;
} }
@ -43,7 +43,7 @@ if ( $action == 'Save' ) {
} }
$view = 'none'; $view = 'none';
} else { } else {
Error("Unknown action $action in saving Storage"); ZM\Error("Unknown action $action in saving Storage");
} }
?> ?>

View File

@ -20,7 +20,7 @@
// System edit actions // System edit actions
if ( !canEdit('System') ) { if ( !canEdit('System') ) {
Warning("Need System permissions to update version"); ZM\Warning('Need System permissions to update version');
return; return;
} }
if ( $action == 'version' && isset($_REQUEST['option']) ) { if ( $action == 'version' && isset($_REQUEST['option']) ) {

View File

@ -20,7 +20,7 @@
if ( !empty($_REQUEST['mid']) && canEdit('Monitors', $_REQUEST['mid']) ) { if ( !empty($_REQUEST['mid']) && canEdit('Monitors', $_REQUEST['mid']) ) {
$mid = validInt($_REQUEST['mid']); $mid = validInt($_REQUEST['mid']);
$monitor = new Monitor($mid); $monitor = new ZM\Monitor($mid);
if ( $action == 'delete' ) { if ( $action == 'delete' ) {
if ( isset($_REQUEST['markZids']) ) { if ( isset($_REQUEST['markZids']) ) {

View File

@ -89,7 +89,7 @@ function userLogin($username='', $password='', $passwordHashed=false) {
} }
$_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking $_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking
if ( $dbUser = dbFetchOne($sql, NULL, $sql_values) ) { if ( $dbUser = dbFetchOne($sql, NULL, $sql_values) ) {
Info("Login successful for user \"$username\""); ZM\Info("Login successful for user \"$username\"");
$user = $dbUser; $user = $dbUser;
unset($_SESSION['loginFailed']); unset($_SESSION['loginFailed']);
if ( ZM_AUTH_TYPE == 'builtin' ) { if ( ZM_AUTH_TYPE == 'builtin' ) {
@ -97,7 +97,7 @@ function userLogin($username='', $password='', $passwordHashed=false) {
} }
zm_session_regenerate_id(); zm_session_regenerate_id();
} else { } else {
Warning("Login denied for user \"$username\""); ZM\Warning("Login denied for user \"$username\"");
$_SESSION['loginFailed'] = true; $_SESSION['loginFailed'] = true;
unset($user); unset($user);
} }
@ -108,7 +108,7 @@ function userLogin($username='', $password='', $passwordHashed=false) {
function userLogout() { function userLogout() {
global $user; global $user;
Info('User "'.$user['Username'].'" logged out'); ZM\Info('User "'.$user['Username'].'" logged out');
unset($user); unset($user);
zm_session_clear(); zm_session_clear();
} }
@ -119,7 +119,7 @@ function getAuthUser($auth) {
if ( ZM_AUTH_HASH_IPS ) { if ( ZM_AUTH_HASH_IPS ) {
$remoteAddr = $_SERVER['REMOTE_ADDR']; $remoteAddr = $_SERVER['REMOTE_ADDR'];
if ( !$remoteAddr ) { if ( !$remoteAddr ) {
Error("Can't determine remote address for authentication, using empty string"); ZM\Error("Can't determine remote address for authentication, using empty string");
$remoteAddr = ''; $remoteAddr = '';
} }
} }
@ -145,7 +145,7 @@ function getAuthUser($auth) {
} // end foreach hour } // end foreach hour
} // end foreach user } // end foreach user
} // end if using auth hash } // end if using auth hash
Error("Unable to authenticate user from auth hash '$auth'"); ZM\Error("Unable to authenticate user from auth hash '$auth'");
return false; return false;
} // end getAuthUser($auth) } // end getAuthUser($auth)
@ -164,7 +164,7 @@ function generateAuthHash($useRemoteAddr, $force=false) {
} else { } else {
$authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$local_time[2].$local_time[3].$local_time[4].$local_time[5]; $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
} }
#Logger::Debug("Generated using hour:".$local_time[2] . ' mday:' . $local_time[3] . ' month:'.$local_time[4] . ' year: ' . $local_time[5] ); #ZM\Logger::Debug("Generated using hour:".$local_time[2] . ' mday:' . $local_time[3] . ' month:'.$local_time[4] . ' year: ' . $local_time[5] );
$auth = md5($authKey); $auth = md5($authKey);
if ( !$force ) { if ( !$force ) {
$close_session = 0; $close_session = 0;
@ -178,9 +178,9 @@ function generateAuthHash($useRemoteAddr, $force=false) {
} else { } else {
return $auth; return $auth;
} }
#Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" ); #ZM\Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" );
#} else { #} else {
#Logger::Debug("Using cached auth " . $_SESSION['AuthHash'] ." beacuse generatedat:" . $_SESSION['AuthHashGeneratedAt'] . ' < now:'. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '. $mintime); #ZM\Logger::Debug("Using cached auth " . $_SESSION['AuthHash'] ." beacuse generatedat:" . $_SESSION['AuthHashGeneratedAt'] . ' < now:'. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '. $mintime);
} # end if AuthHash is not cached } # end if AuthHash is not cached
return $_SESSION['AuthHash'.$_SESSION['remoteAddr']]; return $_SESSION['AuthHash'.$_SESSION['remoteAddr']];
} # end if using AUTH and AUTH_RELAY } # end if using AUTH and AUTH_RELAY

View File

@ -138,7 +138,7 @@ define( 'MYSQL_FMT_DATETIME_SHORT', '%y/%m/%d %H:%i:%S' ); // MySQL date_format
require_once( 'database.php' ); require_once( 'database.php' );
require_once( 'logger.php' ); require_once( 'logger.php' );
loadConfig(); loadConfig();
Logger::fetch()->initialise(); ZM\Logger::fetch()->initialise();
$GLOBALS['defaultUser'] = array( $GLOBALS['defaultUser'] = array(
'Username' => 'admin', 'Username' => 'admin',

View File

@ -288,9 +288,13 @@ function csrf_callback($tokens) {
echo "<html><head><title>CSRF check failed</title></head> echo "<html><head><title>CSRF check failed</title></head>
<body> <body>
<p>CSRF check failed. Your form session may have expired, or you may not have <p>CSRF check failed. Your form session may have expired, or you may not have
cookies enabled.</p> cookies enabled.</p>";
<form method='post' action=''>$data<input type='submit' value='Try again' /></form> if (ZM_LOG_DEBUG) {
<p>Debug: $tokens</p></body></html> // Don't make it too easy for users to inflict a CSRF attack on themselves.
echo "<p><strong>Only try again if you weren't sent to this page by someone as this is potentially a sign of an attack.</strong></p>";
echo "<form method='post' action=''>$data<input type='submit' value='Try again' /></form>";
}
echo "<p>Debug: $tokens</p></body></html>
"; ";
} }

View File

@ -93,7 +93,7 @@ function dbLog( $sql, $update=false ) {
global $dbLogLevel; global $dbLogLevel;
$noExecute = $update && ($dbLogLevel >= DB_LOG_DEBUG); $noExecute = $update && ($dbLogLevel >= DB_LOG_DEBUG);
if ( $dbLogLevel > DB_LOG_OFF ) if ( $dbLogLevel > DB_LOG_OFF )
Logger::Debug( "SQL-LOG: $sql".($noExecute?" (not executed)":"") ); ZM\Logger::Debug( "SQL-LOG: $sql".($noExecute?" (not executed)":"") );
return( $noExecute ); return( $noExecute );
} }
@ -104,7 +104,7 @@ function dbError( $sql ) {
return ''; return '';
$message = "SQL-ERR '".implode("\n",$dbConn->errorInfo())."', statement was '".$sql."'"; $message = "SQL-ERR '".implode("\n",$dbConn->errorInfo())."', statement was '".$sql."'";
Error($message); ZM\Error($message);
return $message; return $message;
} }
@ -130,32 +130,32 @@ function dbQuery( $sql, $params=NULL ) {
try { try {
if ( isset($params) ) { if ( isset($params) ) {
if ( ! $result = $dbConn->prepare( $sql ) ) { if ( ! $result = $dbConn->prepare( $sql ) ) {
Error("SQL: Error preparing $sql: " . $pdo->errorInfo); ZM\Error("SQL: Error preparing $sql: " . $pdo->errorInfo);
return NULL; return NULL;
} }
if ( ! $result->execute( $params ) ) { if ( ! $result->execute( $params ) ) {
Error("SQL: Error executing $sql: " . implode(',', $result->errorInfo() ) ); ZM\Error("SQL: Error executing $sql: " . implode(',', $result->errorInfo() ) );
return NULL; return NULL;
} }
} else { } else {
if ( defined('ZM_DB_DEBUG') ) { if ( defined('ZM_DB_DEBUG') ) {
Logger::Debug("SQL: $sql values:" . ($params?implode(',',$params):'') ); ZM\Logger::Debug("SQL: $sql values:" . ($params?implode(',',$params):'') );
} }
$result = $dbConn->query($sql); $result = $dbConn->query($sql);
if ( ! $result ) { if ( ! $result ) {
Error("SQL: Error preparing $sql: " . $pdo->errorInfo); ZM\Error("SQL: Error preparing $sql: " . $pdo->errorInfo);
return NULL; return NULL;
} }
} }
if ( defined('ZM_DB_DEBUG') ) { if ( defined('ZM_DB_DEBUG') ) {
if ( $params ) if ( $params )
Logger::Debug("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() ); ZM\Logger::Debug("SQL: $sql" . implode(',',$params) . ' rows: '.$result->rowCount() );
else else
Logger::Debug("SQL: $sql: rows:" . $result->rowCount() ); ZM\Logger::Debug("SQL: $sql: rows:" . $result->rowCount() );
} }
} catch(PDOException $e) { } catch(PDOException $e) {
Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') ); ZM\Error( "SQL-ERR '".$e->getMessage()."', statement was '".$sql."' params:" . ($params?implode(',',$params):'') );
return NULL; return NULL;
} }
return $result; return $result;
@ -164,7 +164,7 @@ function dbQuery( $sql, $params=NULL ) {
function dbFetchOne( $sql, $col=false, $params=NULL ) { function dbFetchOne( $sql, $col=false, $params=NULL ) {
$result = dbQuery( $sql, $params ); $result = dbQuery( $sql, $params );
if ( ! $result ) { if ( ! $result ) {
Error( "SQL-ERR dbFetchOne no result, statement was '".$sql."'" . ( $params ? 'params: ' . join(',',$params) : '' ) ); ZM\Error( "SQL-ERR dbFetchOne no result, statement was '".$sql."'" . ( $params ? 'params: ' . join(',',$params) : '' ) );
return false; return false;
} }
if ( ! $result->rowCount() ) { if ( ! $result->rowCount() ) {
@ -175,7 +175,7 @@ function dbFetchOne( $sql, $col=false, $params=NULL ) {
if ( $result && $dbRow = $result->fetch(PDO::FETCH_ASSOC) ) { if ( $result && $dbRow = $result->fetch(PDO::FETCH_ASSOC) ) {
if ( $col ) { if ( $col ) {
if ( ! array_key_exists($col, $dbRow) ) { if ( ! array_key_exists($col, $dbRow) ) {
Warning("$col does not exist in the returned row " . print_r($dbRow, true)); ZM\Warning("$col does not exist in the returned row " . print_r($dbRow, true));
} }
return $dbRow[$col]; return $dbRow[$col];
} }
@ -187,7 +187,7 @@ function dbFetchOne( $sql, $col=false, $params=NULL ) {
function dbFetchAll( $sql, $col=false, $params=NULL ) { function dbFetchAll( $sql, $col=false, $params=NULL ) {
$result = dbQuery( $sql, $params ); $result = dbQuery( $sql, $params );
if ( ! $result ) { if ( ! $result ) {
Error( "SQL-ERR dbFetchAll no result, statement was '".$sql."'" . ( $params ? 'params: ' .join(',', $params) : '' ) ); ZM\Error( "SQL-ERR dbFetchAll no result, statement was '".$sql."'" . ( $params ? 'params: ' .join(',', $params) : '' ) );
return false; return false;
} }
@ -294,7 +294,7 @@ function getTableDescription( $table, $asString=1 ) {
//$desc['minLength'] = -128; //$desc['minLength'] = -128;
break; break;
default : default :
Error( "Unexpected text qualifier '".$matches[1]."' found for field '".$row['Field']."' in table '".$table."'" ); ZM\Error( "Unexpected text qualifier '".$matches[1]."' found for field '".$row['Field']."' in table '".$table."'" );
break; break;
} }
} elseif ( preg_match( "/^(enum|set)\((.*)\)$/", $row['Type'], $matches ) ) { } elseif ( preg_match( "/^(enum|set)\((.*)\)$/", $row['Type'], $matches ) ) {
@ -326,7 +326,7 @@ function getTableDescription( $table, $asString=1 ) {
//$desc['maxValue'] = 127; //$desc['maxValue'] = 127;
break; break;
default : default :
Error( "Unexpected integer qualifier '".$matches[1]."' found for field '".$row['Field']."' in table '".$table."'" ); ZM\Error( "Unexpected integer qualifier '".$matches[1]."' found for field '".$row['Field']."' in table '".$table."'" );
break; break;
} }
if ( !empty($matches[1]) ) if ( !empty($matches[1]) )
@ -361,7 +361,7 @@ function getTableDescription( $table, $asString=1 ) {
break; break;
} }
} else { } else {
Error( "Can't parse database type '".$row['Type']."' found for field '".$row['Field']."' in table '".$table."'" ); ZM\Error( "Can't parse database type '".$row['Type']."' found for field '".$row['Field']."' in table '".$table."'" );
} }
if ( $asString ) if ( $asString )

View File

@ -53,7 +53,11 @@ function CSPHeaders($view, $nonce) {
case 'controlcap': case 'controlcap':
case 'cycle': case 'cycle':
case 'donate': case 'donate':
case 'download':
case 'error': case 'error':
case 'events':
case 'export':
case 'frame':
case 'function': case 'function':
case 'log': case 'log':
case 'logout': case 'logout':
@ -86,12 +90,12 @@ function CORSHeaders() {
# The following is left for future reference/use. # The following is left for future reference/use.
$valid = false; $valid = false;
$Servers = Server::find(); $Servers = ZM\Server::find();
if ( sizeof($Servers) < 1 ) { if ( sizeof($Servers) < 1 ) {
# Only need CORSHeaders in the event that there are multiple servers in use. # Only need CORSHeaders in the event that there are multiple servers in use.
# ICON: Might not be true. multi-port? # ICON: Might not be true. multi-port?
if ( ZM_MIN_STREAMING_PORT ) { if ( ZM_MIN_STREAMING_PORT ) {
Logger::Debug("Setting default Access-Control-Allow-Origin from " . $_SERVER['HTTP_ORIGIN']); ZM\Logger::Debug('Setting default Access-Control-Allow-Origin from ' . $_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Headers: x-requested-with,x-request'); header('Access-Control-Allow-Headers: x-requested-with,x-request');
} }
@ -104,14 +108,14 @@ function CORSHeaders() {
preg_match('/^(https?:\/\/)?'.preg_quote($Server->Name(),'/').'/i', $_SERVER['HTTP_ORIGIN']) preg_match('/^(https?:\/\/)?'.preg_quote($Server->Name(),'/').'/i', $_SERVER['HTTP_ORIGIN'])
) { ) {
$valid = true; $valid = true;
Logger::Debug("Setting Access-Control-Allow-Origin from " . $_SERVER['HTTP_ORIGIN']); ZM\Logger::Debug("Setting Access-Control-Allow-Origin from " . $_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Headers: x-requested-with,x-request'); header('Access-Control-Allow-Headers: x-requested-with,x-request');
break; break;
} }
} }
if ( !$valid ) { if ( !$valid ) {
Warning($_SERVER['HTTP_ORIGIN'] . ' is not found in servers list.'); ZM\Warning($_SERVER['HTTP_ORIGIN'] . ' is not found in servers list.');
} }
} }
} }
@ -290,7 +294,7 @@ function getImageStreamHTML( $id, $src, $width, $height, $title='' ) {
function outputControlStream( $src, $width, $height, $monitor, $scale, $target ) { function outputControlStream( $src, $width, $height, $monitor, $scale, $target ) {
?> ?>
<form name="ctrlForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>" target="<?php echo $target ?>"> <form name="ctrlForm" method="post" action="?" target="<?php echo $target ?>">
<input type="hidden" name="view" value="blank"> <input type="hidden" name="view" value="blank">
<input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>"> <input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>">
<input type="hidden" name="action" value="control"> <input type="hidden" name="action" value="control">
@ -360,7 +364,7 @@ function getWebSiteUrl( $id, $src, $width, $height, $title='' ) {
function outputControlStill( $src, $width, $height, $monitor, $scale, $target ) { function outputControlStill( $src, $width, $height, $monitor, $scale, $target ) {
?> ?>
<form name="ctrlForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>" target="<?php echo $target ?>"> <form name="ctrlForm" method="post" action="?" target="<?php echo $target ?>">
<input type="hidden" name="view" value="blank"> <input type="hidden" name="view" value="blank">
<input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>"> <input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>">
<input type="hidden" name="action" value="control"> <input type="hidden" name="action" value="control">
@ -405,7 +409,7 @@ function getZmuCommand( $args ) {
} }
function getEventDefaultVideoPath( $event ) { function getEventDefaultVideoPath( $event ) {
$Event = new Event( $event ); $Event = new ZM\Event( $event );
return $Event->getStreamSrc( array( 'mode'=>'mpeg', 'format'=>'h264' ) ); return $Event->getStreamSrc( array( 'mode'=>'mpeg', 'format'=>'h264' ) );
} }
@ -420,15 +424,15 @@ function deletePath( $path ) {
function deleteEvent( $event ) { function deleteEvent( $event ) {
if ( empty($event) ) { if ( empty($event) ) {
Error( 'Empty event passed to deleteEvent.'); ZM\Error('Empty event passed to deleteEvent.');
return; return;
} }
if ( gettype($event) != 'array' ) { if ( gettype($event) != 'array' ) {
# $event could be an eid, so turn it into an event hash # $event could be an eid, so turn it into an event hash
$event = new Event( $event ); $event = new ZM\Event( $event );
} else { } else {
Logger::Debug("Event type: " . gettype($event)); ZM\Logger::Debug("Event type: " . gettype($event));
} }
global $user; global $user;
@ -494,7 +498,6 @@ function makePopupButton( $url, $winName, $winSize, $buttonValue, $condition=1,
} }
function htmlSelect( $name, $contents, $values, $behaviours=false ) { function htmlSelect( $name, $contents, $values, $behaviours=false ) {
$behaviourText = ''; $behaviourText = '';
if ( !empty($behaviours) ) { if ( !empty($behaviours) ) {
if ( is_array($behaviours) ) { if ( is_array($behaviours) ) {
@ -524,7 +527,7 @@ function htmlOptions($contents, $values) {
if ( isset($option['disabled']) ) { if ( isset($option['disabled']) ) {
$disabled = $option['disabled']; $disabled = $option['disabled'];
Error("Setting to disabled"); ZM\Error("Setting to disabled");
} }
} else if ( is_object($option) ) { } else if ( is_object($option) ) {
$text = $option->Name(); $text = $option->Name();
@ -532,10 +535,10 @@ function htmlOptions($contents, $values) {
$text = $option; $text = $option;
} }
$selected = is_array($values) ? in_array($value, $values) : !strcmp($value, $values); $selected = is_array($values) ? in_array($value, $values) : !strcmp($value, $values);
$options_html .= "<option value=\"$value\"". $options_html .= "<option value=\"".htmlspecialchars($value, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false)."\"".
($selected?' selected="selected"':''). ($selected?' selected="selected"':'').
($disabled?' disabled="disabled"':''). ($disabled?' disabled="disabled"':'').
">$text</option>"; ">".htmlspecialchars($text, ENT_COMPAT | ENT_HTML401, ini_get('default_charset'), false)."</option>";
} }
return $options_html; return $options_html;
} }
@ -553,7 +556,7 @@ function buildSelect( $name, $contents, $behaviours=false ) {
elseif ( isset($_REQUEST[$arr]) ) elseif ( isset($_REQUEST[$arr]) )
$value = $_REQUEST[$arr]; $value = $_REQUEST[$arr];
if ( !preg_match_all( '/\[\s*[\'"]?(\w+)["\']?\s*\]/', $matches[2], $matches ) ) { if ( !preg_match_all( '/\[\s*[\'"]?(\w+)["\']?\s*\]/', $matches[2], $matches ) ) {
Fatal( "Can't parse selector '$name'" ); ZM\Fatal( "Can't parse selector '$name'" );
} }
for ( $i = 0; $i < count($matches[1]); $i++ ) { for ( $i = 0; $i < count($matches[1]); $i++ ) {
$idx = $matches[1][$i]; $idx = $matches[1][$i];
@ -830,17 +833,17 @@ function daemonControl( $command, $daemon=false, $args=false ) {
} }
$string = escapeshellcmd( $string ); $string = escapeshellcmd( $string );
#$string .= ' 2>/dev/null >&- <&- >/dev/null'; #$string .= ' 2>/dev/null >&- <&- >/dev/null';
Logger::Debug("daemonControl $string"); ZM\Logger::Debug("daemonControl $string");
exec( $string ); exec( $string );
} }
function zmcControl($monitor, $mode=false) { function zmcControl($monitor, $mode=false) {
$Monitor = new Monitor( $monitor ); $Monitor = new ZM\Monitor( $monitor );
return $Monitor->zmcControl($mode); return $Monitor->zmcControl($mode);
} }
function zmaControl($monitor, $mode=false) { function zmaControl($monitor, $mode=false) {
$Monitor = new Monitor($monitor); $Monitor = new ZM\Monitor($monitor);
return $Monitor->zmaControl($mode); return $Monitor->zmaControl($mode);
} }
@ -913,7 +916,7 @@ function zmaCheck( $monitor ) {
} }
function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) { function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $overwrite=false ) {
$Event = new Event( $event ); $Event = new ZM\Event( $event );
return $Event->getImageSrc( $frame, $scale, $captureOnly, $overwrite ); return $Event->getImageSrc( $frame, $scale, $captureOnly, $overwrite );
} }
@ -937,7 +940,7 @@ function createListThumbnail( $event, $overwrite=false ) {
$scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_HEIGHT)/$event['Height']; $scale = (SCALE_BASE*ZM_WEB_LIST_THUMB_HEIGHT)/$event['Height'];
$thumbWidth = reScale( $event['Width'], $scale ); $thumbWidth = reScale( $event['Width'], $scale );
} else { } else {
Fatal( "No thumbnail width or height specified, please check in Options->Web" ); ZM\Fatal( "No thumbnail width or height specified, please check in Options->Web" );
} }
$imageData = getImageSrc( $event, $frame, $scale, false, $overwrite ); $imageData = getImageSrc( $event, $frame, $scale, false, $overwrite );
@ -1083,7 +1086,7 @@ function parseSort( $saveToSession=false, $querySep='&amp;' ) {
$_SESSION['sort_asc'] = validHtmlStr($_REQUEST['sort_asc']); $_SESSION['sort_asc'] = validHtmlStr($_REQUEST['sort_asc']);
} }
if ($_REQUEST['limit'] != '') { if ($_REQUEST['limit'] != '') {
$limitQuery = "&limit=".$_REQUEST['limit']; $limitQuery = "&limit=".validInt($_REQUEST['limit']);
} }
} }
@ -1193,11 +1196,11 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
if ( ! $StorageArea ) { if ( ! $StorageArea ) {
for ( $j = 0; $j < count($terms); $j++ ) { for ( $j = 0; $j < count($terms); $j++ ) {
if ( isset($terms[$j]['attr']) and $terms[$j]['attr'] == 'StorageId' and isset($terms[$j]['val']) ) { if ( isset($terms[$j]['attr']) and $terms[$j]['attr'] == 'StorageId' and isset($terms[$j]['val']) ) {
$StorageArea = new Storage($terms[$j]['val']); $StorageArea = new ZM\Storage($terms[$j]['val']);
break; break;
} }
} // end foreach remaining term } // end foreach remaining term
if ( ! $StorageArea ) $StorageArea = new Storage(); if ( ! $StorageArea ) $StorageArea = new ZM\Storage();
} // end no StorageArea found yet } // end no StorageArea found yet
$filter['sql'] .= getDiskPercent( $StorageArea->Path() ); $filter['sql'] .= getDiskPercent( $StorageArea->Path() );
@ -1207,7 +1210,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
if ( ! $StorageArea ) { if ( ! $StorageArea ) {
for ( $j = $i; $j < count($terms); $j++ ) { for ( $j = $i; $j < count($terms); $j++ ) {
if ( isset($terms[$i]['attr']) and $terms[$i]['attr'] == 'StorageId' and isset($terms[$j]['val']) ) { if ( isset($terms[$i]['attr']) and $terms[$i]['attr'] == 'StorageId' and isset($terms[$j]['val']) ) {
$StorageArea = new Storage($terms[$i]['val']); $StorageArea = new ZM\Storage($terms[$i]['val']);
} }
} // end foreach remaining term } // end foreach remaining term
} // end no StorageArea found yet } // end no StorageArea found yet
@ -1239,7 +1242,7 @@ function parseFilter(&$filter, $saveToSession=false, $querySep='&amp;') {
} }
break; break;
case 'StorageId': case 'StorageId':
$StorageArea = new Storage( $value ); $StorageArea = new ZM\Storage( $value );
if ( $value != 'NULL' ) if ( $value != 'NULL' )
$value = dbEscape($value); $value = dbEscape($value);
break; break;
@ -1424,7 +1427,7 @@ function getPagination( $pages, $page, $maxShortcuts, $query, $querySep='&amp;'
function sortHeader( $field, $querySep='&amp;' ) { function sortHeader( $field, $querySep='&amp;' ) {
global $view; global $view;
return( '?view='.$view.$querySep.'page=1'.$_REQUEST['filter']['query'].$querySep.'sort_field='.$field.$querySep.'sort_asc='.($_REQUEST['sort_field'] == $field?!$_REQUEST['sort_asc']:0).$querySep.'limit='.$_REQUEST['limit'] ); return '?view='.$view.$querySep.'page=1'.$_REQUEST['filter']['query'].$querySep.'sort_field='.$field.$querySep.'sort_asc='.($_REQUEST['sort_field'] == $field?!$_REQUEST['sort_asc']:0).$querySep.'limit='.validInt($_REQUEST['limit']);
} }
function sortTag( $field ) { function sortTag( $field ) {
@ -1459,7 +1462,7 @@ function getDiskPercent($path = ZM_DIR_EVENTS) {
} }
function getDiskBlocks() { function getDiskBlocks() {
if ( ! $StorageArea ) $StorageArea = new Storage(); if ( ! $StorageArea ) $StorageArea = new ZM\Storage();
$df = shell_exec( 'df '.escapeshellarg($StorageArea->Path() )); $df = shell_exec( 'df '.escapeshellarg($StorageArea->Path() ));
$space = -1; $space = -1;
if ( preg_match( '/\s(\d+)\s+\d+\s+\d+%/ms', $df, $matches ) ) if ( preg_match( '/\s(\d+)\s+\d+\s+\d+%/ms', $df, $matches ) )
@ -1844,17 +1847,17 @@ function coordsToPoints( $coords ) {
function limitPoints( &$points, $min_x, $min_y, $max_x, $max_y ) { function limitPoints( &$points, $min_x, $min_y, $max_x, $max_y ) {
foreach ( $points as &$point ) { foreach ( $points as &$point ) {
if ( $point['x'] < $min_x ) { if ( $point['x'] < $min_x ) {
Logger::Debug('Limiting point x'.$point['x'].' to min_x ' . $min_x ); ZM\Logger::Debug('Limiting point x'.$point['x'].' to min_x ' . $min_x );
$point['x'] = $min_x; $point['x'] = $min_x;
} else if ( $point['x'] > $max_x ) { } else if ( $point['x'] > $max_x ) {
Logger::Debug('Limiting point x'.$point['x'].' to max_x ' . $max_x ); ZM\Logger::Debug('Limiting point x'.$point['x'].' to max_x ' . $max_x );
$point['x'] = $max_x; $point['x'] = $max_x;
} }
if ( $point['y'] < $min_y ) { if ( $point['y'] < $min_y ) {
Logger::Debug('Limiting point y'.$point['y'].' to min_y ' . $min_y ); ZM\Logger::Debug('Limiting point y'.$point['y'].' to min_y ' . $min_y );
$point['y'] = $min_y; $point['y'] = $min_y;
} else if ( $point['y'] > $max_y ) { } else if ( $point['y'] > $max_y ) {
Logger::Debug('Limiting point y'.$point['y'].' to max_y ' . $max_y ); ZM\Logger::Debug('Limiting point y'.$point['y'].' to max_y ' . $max_y );
$point['y'] = $max_y; $point['y'] = $max_y;
} }
} // end foreach point } // end foreach point
@ -1909,13 +1912,13 @@ function initX10Status() {
if ( !isset($x10_status) ) { if ( !isset($x10_status) ) {
$socket = socket_create( AF_UNIX, SOCK_STREAM, 0 ); $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 );
if ( $socket < 0 ) { if ( $socket < 0 ) {
Fatal( 'socket_create() failed: '.socket_strerror($socket) ); ZM\Fatal( 'socket_create() failed: '.socket_strerror($socket) );
} }
$sock_file = ZM_PATH_SOCKS.'/zmx10.sock'; $sock_file = ZM_PATH_SOCKS.'/zmx10.sock';
if ( @socket_connect( $socket, $sock_file ) ) { if ( @socket_connect( $socket, $sock_file ) ) {
$command = 'status'; $command = 'status';
if ( !socket_write( $socket, $command ) ) { if ( !socket_write( $socket, $command ) ) {
Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) ); ZM\Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) );
} }
socket_shutdown( $socket, 1 ); socket_shutdown( $socket, 1 );
$x10Output = ''; $x10Output = '';
@ -1951,13 +1954,13 @@ function getDeviceStatusX10( $key ) {
function setDeviceStatusX10( $key, $status ) { function setDeviceStatusX10( $key, $status ) {
$socket = socket_create( AF_UNIX, SOCK_STREAM, 0 ); $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 );
if ( $socket < 0 ) { if ( $socket < 0 ) {
Fatal( 'socket_create() failed: '.socket_strerror($socket) ); ZM\Fatal( 'socket_create() failed: '.socket_strerror($socket) );
} }
$sock_file = ZM_PATH_SOCKS.'/zmx10.sock'; $sock_file = ZM_PATH_SOCKS.'/zmx10.sock';
if ( @socket_connect( $socket, $sock_file ) ) { if ( @socket_connect( $socket, $sock_file ) ) {
$command = "$status;$key"; $command = "$status;$key";
if ( !socket_write( $socket, $command ) ) { if ( !socket_write( $socket, $command ) ) {
Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) ); ZM\Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) );
} }
socket_shutdown( $socket, 1 ); socket_shutdown( $socket, 1 );
$x10Response = socket_read( $socket, 256 ); $x10Response = socket_read( $socket, 256 );
@ -1980,18 +1983,18 @@ function logState() {
$state = 'ok'; $state = 'ok';
$levelCounts = array( $levelCounts = array(
Logger::FATAL => array( ZM_LOG_ALERT_FAT_COUNT, ZM_LOG_ALARM_FAT_COUNT ), ZM\Logger::FATAL => array( ZM_LOG_ALERT_FAT_COUNT, ZM_LOG_ALARM_FAT_COUNT ),
Logger::ERROR => array( ZM_LOG_ALERT_ERR_COUNT, ZM_LOG_ALARM_ERR_COUNT ), ZM\Logger::ERROR => array( ZM_LOG_ALERT_ERR_COUNT, ZM_LOG_ALARM_ERR_COUNT ),
Logger::WARNING => array( ZM_LOG_ALERT_WAR_COUNT, ZM_LOG_ALARM_WAR_COUNT ), ZM\Logger::WARNING => array( ZM_LOG_ALERT_WAR_COUNT, ZM_LOG_ALARM_WAR_COUNT ),
); );
# This is an expensive request, as it has to hit every row of the Logs Table # This is an expensive request, as it has to hit every row of the Logs Table
$sql = 'SELECT Level, COUNT(Level) AS LevelCount FROM Logs WHERE Level < '.Logger::INFO.' AND TimeKey > unix_timestamp(now() - interval '.ZM_LOG_CHECK_PERIOD.' second) GROUP BY Level ORDER BY Level ASC'; $sql = 'SELECT Level, COUNT(Level) AS LevelCount FROM Logs WHERE Level < '.ZM\Logger::INFO.' AND TimeKey > unix_timestamp(now() - interval '.ZM_LOG_CHECK_PERIOD.' second) GROUP BY Level ORDER BY Level ASC';
$counts = dbFetchAll($sql); $counts = dbFetchAll($sql);
if ( $counts ) { if ( $counts ) {
foreach ( $counts as $count ) { foreach ( $counts as $count ) {
if ( $count['Level'] <= Logger::PANIC ) if ( $count['Level'] <= ZM\Logger::PANIC )
$count['Level'] = Logger::FATAL; $count['Level'] = ZM\Logger::FATAL;
if ( !($levelCount = $levelCounts[$count['Level']]) ) { if ( !($levelCount = $levelCounts[$count['Level']]) ) {
Error('Unexpected Log level '.$count['Level']); Error('Unexpected Log level '.$count['Level']);
next; next;
@ -2023,15 +2026,15 @@ function checkJsonError($value) {
$value = var_export($value,true); $value = var_export($value,true);
switch( json_last_error() ) { switch( json_last_error() ) {
case JSON_ERROR_DEPTH : case JSON_ERROR_DEPTH :
Fatal( "Unable to decode JSON string '$value', maximum stack depth exceeded" ); ZM\Fatal( "Unable to decode JSON string '$value', maximum stack depth exceeded" );
case JSON_ERROR_CTRL_CHAR : case JSON_ERROR_CTRL_CHAR :
Fatal( "Unable to decode JSON string '$value', unexpected control character found" ); ZM\Fatal( "Unable to decode JSON string '$value', unexpected control character found" );
case JSON_ERROR_STATE_MISMATCH : case JSON_ERROR_STATE_MISMATCH :
Fatal( "Unable to decode JSON string '$value', invalid or malformed JSON" ); ZM\Fatal( "Unable to decode JSON string '$value', invalid or malformed JSON" );
case JSON_ERROR_SYNTAX : case JSON_ERROR_SYNTAX :
Fatal( "Unable to decode JSON string '$value', syntax error" ); ZM\Fatal( "Unable to decode JSON string '$value', syntax error" );
default : default :
Fatal( "Unable to decode JSON string '$value', unexpected error ".json_last_error() ); ZM\Fatal( "Unable to decode JSON string '$value', unexpected error ".json_last_error() );
case JSON_ERROR_NONE: case JSON_ERROR_NONE:
break; break;
} }
@ -2119,7 +2122,7 @@ define( 'HTTP_STATUS_BAD_REQUEST', 400 );
define( 'HTTP_STATUS_FORBIDDEN', 403 ); define( 'HTTP_STATUS_FORBIDDEN', 403 );
function ajaxError( $message, $code=HTTP_STATUS_OK ) { function ajaxError( $message, $code=HTTP_STATUS_OK ) {
Error( $message ); ZM\Error( $message );
if ( function_exists( 'ajaxCleanup' ) ) if ( function_exists( 'ajaxCleanup' ) )
ajaxCleanup(); ajaxCleanup();
if ( $code == HTTP_STATUS_OK ) { if ( $code == HTTP_STATUS_OK ) {
@ -2165,7 +2168,7 @@ function cache_bust( $file ) {
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;
} else { } else {
Warning("Failed linking $file to $cacheFile"); ZM\Warning("Failed linking $file to $cacheFile");
} }
return $file; return $file;
} }
@ -2289,7 +2292,7 @@ function getStreamHTML( $monitor, $options = array() ) {
$monitor->Name()); $monitor->Name());
} else { } else {
if ( $options['mode'] == 'stream' ) { if ( $options['mode'] == 'stream' ) {
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' ); ZM\Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' );
} }
$options['mode'] = 'single'; $options['mode'] = 'single';
$streamSrc = $monitor->getStreamSrc( $options ); $streamSrc = $monitor->getStreamSrc( $options );
@ -2305,7 +2308,7 @@ function getStreamMode( ) {
$streamMode = 'jpeg'; $streamMode = 'jpeg';
} else { } else {
$streamMode = 'single'; $streamMode = 'single';
Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' ); ZM\Info( 'The system has fallen back to single jpeg mode for streaming. Consider enabling Cambozola or upgrading the client browser.' );
} }
return $streamMode; return $streamMode;
} // end function getStreamMode } // end function getStreamMode
@ -2346,13 +2349,13 @@ function check_timezone() {
#"); #");
if ( $sys_tzoffset != $php_tzoffset ) if ( $sys_tzoffset != $php_tzoffset )
Fatal("ZoneMinder is not installed properly: php's date.timezone does not match the system timezone!"); ZM\Fatal("ZoneMinder is not installed properly: php's date.timezone does not match the system timezone!");
if ( $sys_tzoffset != $mysql_tzoffset ) if ( $sys_tzoffset != $mysql_tzoffset )
Error("ZoneMinder is not installed properly: mysql's timezone does not match the system timezone! Event lists will display incorrect times."); ZM\Error("ZoneMinder is not installed properly: mysql's timezone does not match the system timezone! Event lists will display incorrect times.");
if (!ini_get('date.timezone') || !date_default_timezone_set(ini_get('date.timezone'))) if (!ini_get('date.timezone') || !date_default_timezone_set(ini_get('date.timezone')))
Fatal( "ZoneMinder is not installed properly: php's date.timezone is not set to a valid timezone" ); ZM\Fatal( "ZoneMinder is not installed properly: php's date.timezone is not set to a valid timezone" );
} }

View File

@ -1,5 +1,6 @@
<?php <?php
namespace ZM;
require_once( 'config.php' ); require_once( 'config.php' );
class Logger { class Logger {
@ -455,7 +456,10 @@ function Error( $string ) {
function Fatal( $string ) { function Fatal( $string ) {
Logger::fetch()->logPrint( Logger::FATAL, $string ); Logger::fetch()->logPrint( Logger::FATAL, $string );
die( htmlentities($string) ); if (Logger::fetch()->debugOn()) {
echo(htmlentities($string));
}
exit(1);
} }
function Panic( $string ) { function Panic( $string ) {
@ -474,7 +478,10 @@ function Panic( $string ) {
} }
} }
Logger::fetch()->logPrint( Logger::PANIC, $string.$backtrace ); Logger::fetch()->logPrint( Logger::PANIC, $string.$backtrace );
die( $string ); if (Logger::fetch()->debugOn()) {
echo $string;
}
exit(1);
} }
function ErrorHandler( $error, $string, $file, $line ) { function ErrorHandler( $error, $string, $file, $line ) {

View File

@ -17,6 +17,7 @@
// 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.
// //
namespace ZM;
error_reporting(E_ALL); error_reporting(E_ALL);
@ -217,10 +218,9 @@ if ( ZM_OPT_USE_AUTH and !isset($user) and ($view != 'login') ) {
$view = 'none'; $view = 'none';
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login';
$request = null; $request = null;
} else if ( ZM_SHOW_PRIVACY && ($action != 'privacy') && ($view != 'options') && (!$request) && canEdit('System') ) { } else if ( ZM_SHOW_PRIVACY && ($view != 'privacy') && ($view != 'options') && (!$request) && canEdit('System') ) {
$view = 'none'; $view = 'none';
$redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=privacy'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=privacy';
$request = null;
} }
CSPHeaders($view, $cspNonce); CSPHeaders($view, $cspNonce);

View File

@ -15,6 +15,9 @@
.ptzControls input.ptzTextBtn { .ptzControls input.ptzTextBtn {
margin-top: 2px; margin-top: 2px;
} }
.ptzControls button {
border: none;
}
.ptzControls .controlsPanel { .ptzControls .controlsPanel {
margin: 0 auto; margin: 0 auto;

View File

@ -9,8 +9,3 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
#controls a {
width: 40px;
margin-left: -20px;
}

View File

@ -9,8 +9,3 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
#controls a {
width: 40px;
margin-left: -20px;
}

View File

@ -9,8 +9,3 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
#controls a {
width: 40px;
margin-left: -20px;
}

View File

@ -21,104 +21,104 @@
function getControlCommands( $monitor ) { function getControlCommands( $monitor ) {
$cmds = array(); $cmds = array();
$cmds['Wake'] = "wake"; $cmds['Wake'] = 'wake';
$cmds['Sleep'] = "sleep"; $cmds['Sleep'] = 'sleep';
$cmds['Reset'] = "reset"; $cmds['Reset'] = 'reset';
$cmds['PresetSet'] = "presetSet"; $cmds['PresetSet'] = 'presetSet';
$cmds['PresetGoto'] = "presetGoto"; $cmds['PresetGoto'] = 'presetGoto';
$cmds['PresetHome'] = "presetHome"; $cmds['PresetHome'] = 'presetHome';
if ( $monitor->CanZoom() ) { if ( $monitor->CanZoom() ) {
if ( $monitor->CanZoomCon() ) if ( $monitor->CanZoomCon() )
$cmds['ZoomRoot'] = "zoomCon"; $cmds['ZoomRoot'] = 'zoomCon';
elseif ( $monitor->CanZoomRel() ) elseif ( $monitor->CanZoomRel() )
$cmds['ZoomRoot'] = "zoomRel"; $cmds['ZoomRoot'] = 'zoomRel';
elseif ( $monitor->CanZoomAbs() ) elseif ( $monitor->CanZoomAbs() )
$cmds['ZoomRoot'] = "zoomAbs"; $cmds['ZoomRoot'] = 'zoomAbs';
$cmds['ZoomTele'] = $cmds['ZoomRoot']."Tele"; $cmds['ZoomTele'] = $cmds['ZoomRoot'].'Tele';
$cmds['ZoomWide'] = $cmds['ZoomRoot']."Wide"; $cmds['ZoomWide'] = $cmds['ZoomRoot'].'Wide';
$cmds['ZoomStop'] = "zoomStop"; $cmds['ZoomStop'] = 'zoomStop';
$cmds['ZoomAuto'] = "zoomAuto"; $cmds['ZoomAuto'] = 'zoomAuto';
$cmds['ZoomMan'] = "zoomMan"; $cmds['ZoomMan'] = 'zoomMan';
} }
if ( $monitor->CanFocus() ) { if ( $monitor->CanFocus() ) {
if ( $monitor->CanFocusCon() ) if ( $monitor->CanFocusCon() )
$cmds['FocusRoot'] = "focusCon"; $cmds['FocusRoot'] = 'focusCon';
elseif ( $monitor->CanFocusRel() ) elseif ( $monitor->CanFocusRel() )
$cmds['FocusRoot'] = "focusRel"; $cmds['FocusRoot'] = 'focusRel';
elseif ( $monitor->CanFocusAbs() ) elseif ( $monitor->CanFocusAbs() )
$cmds['FocusRoot'] = "focusAbs"; $cmds['FocusRoot'] = 'focusAbs';
$cmds['FocusFar'] = $cmds['FocusRoot']."Far"; $cmds['FocusFar'] = $cmds['FocusRoot'].'Far';
$cmds['FocusNear'] = $cmds['FocusRoot']."Near"; $cmds['FocusNear'] = $cmds['FocusRoot'].'Near';
$cmds['FocusStop'] = "focusStop"; $cmds['FocusStop'] = 'focusStop';
$cmds['FocusAuto'] = "focusAuto"; $cmds['FocusAuto'] = 'focusAuto';
$cmds['FocusMan'] = "focusMan"; $cmds['FocusMan'] = 'focusMan';
} }
if ( $monitor->CanIris() ) { if ( $monitor->CanIris() ) {
if ( $monitor->CanIrisCon() ) if ( $monitor->CanIrisCon() )
$cmds['IrisRoot'] = "irisCon"; $cmds['IrisRoot'] = 'irisCon';
elseif ( $monitor->CanIrisRel() ) elseif ( $monitor->CanIrisRel() )
$cmds['IrisRoot'] = "irisRel"; $cmds['IrisRoot'] = 'irisRel';
elseif ( $monitor->CanIrisAbs() ) elseif ( $monitor->CanIrisAbs() )
$cmds['IrisRoot'] = "irisAbs"; $cmds['IrisRoot'] = 'irisAbs';
$cmds['IrisOpen'] = $cmds['IrisRoot']."Open"; $cmds['IrisOpen'] = $cmds['IrisRoot'].'Open';
$cmds['IrisClose'] = $cmds['IrisRoot']."Close"; $cmds['IrisClose'] = $cmds['IrisRoot'].'Close';
$cmds['IrisStop'] = "irisStop"; $cmds['IrisStop'] = 'irisStop';
$cmds['IrisAuto'] = "irisAuto"; $cmds['IrisAuto'] = 'irisAuto';
$cmds['IrisMan'] = "irisMan"; $cmds['IrisMan'] = 'irisMan';
} }
if ( $monitor->CanWhite() ) { if ( $monitor->CanWhite() ) {
if ( $monitor->CanWhiteCon() ) if ( $monitor->CanWhiteCon() )
$cmds['WhiteRoot'] = "whiteCon"; $cmds['WhiteRoot'] = 'whiteCon';
elseif ( $monitor->CanWhiteRel() ) elseif ( $monitor->CanWhiteRel() )
$cmds['WhiteRoot'] = "whiteRel"; $cmds['WhiteRoot'] = 'whiteRel';
elseif ( $monitor->CanWhiteAbs() ) elseif ( $monitor->CanWhiteAbs() )
$cmds['WhiteRoot'] = "whiteAbs"; $cmds['WhiteRoot'] = 'whiteAbs';
$cmds['WhiteIn'] = $cmds['WhiteRoot']."In"; $cmds['WhiteIn'] = $cmds['WhiteRoot'].'In';
$cmds['WhiteOut'] = $cmds['WhiteRoot']."Out"; $cmds['WhiteOut'] = $cmds['WhiteRoot'].'Out';
$cmds['WhiteAuto'] = "whiteAuto"; $cmds['WhiteAuto'] = 'whiteAuto';
$cmds['WhiteMan'] = "whiteMan"; $cmds['WhiteMan'] = 'whiteMan';
} }
if ( $monitor->CanGain() ) { if ( $monitor->CanGain() ) {
if ( $monitor->CanGainCon() ) if ( $monitor->CanGainCon() )
$cmds['GainRoot'] = "gainCon"; $cmds['GainRoot'] = 'gainCon';
elseif ( $monitor->CanGainRel() ) elseif ( $monitor->CanGainRel() )
$cmds['GainRoot'] = "gainRel"; $cmds['GainRoot'] = 'gainRel';
elseif ( $monitor->CanGainAbs() ) elseif ( $monitor->CanGainAbs() )
$cmds['GainRoot'] = "gainAbs"; $cmds['GainRoot'] = 'gainAbs';
$cmds['GainUp'] = $cmds['GainRoot']."Up"; $cmds['GainUp'] = $cmds['GainRoot'].'Up';
$cmds['GainDown'] = $cmds['GainRoot']."Down"; $cmds['GainDown'] = $cmds['GainRoot'].'Down';
$cmds['GainAuto'] = "gainAuto"; $cmds['GainAuto'] = 'gainAuto';
$cmds['GainMan'] = "gainMan"; $cmds['GainMan'] = 'gainMan';
} }
if ( $monitor->CanMove() ) { if ( $monitor->CanMove() ) {
if ( $monitor->CanMoveCon() ) { if ( $monitor->CanMoveCon() ) {
$cmds['MoveRoot'] = "moveCon"; $cmds['MoveRoot'] = 'moveCon';
$cmds['Center'] = "moveStop"; $cmds['Center'] = 'moveStop';
} elseif ( $monitor->CanMoveRel() ) { } elseif ( $monitor->CanMoveRel() ) {
$cmds['MoveRoot'] = "moveRel"; $cmds['MoveRoot'] = 'moveRel';
$cmds['Center'] = $cmds['PresetHome']; $cmds['Center'] = $cmds['PresetHome'];
} elseif ( $monitor->CanMoveAbs() ) { } elseif ( $monitor->CanMoveAbs() ) {
$cmds['MoveRoot'] = "moveAbs"; $cmds['MoveRoot'] = 'moveAbs';
$cmds['Center'] = $cmds['PresetHome']; $cmds['Center'] = $cmds['PresetHome'];
} else { } else {
$cmds['MoveRoot'] = ''; $cmds['MoveRoot'] = '';
} }
$cmds['MoveUp'] = $cmds['MoveRoot']."Up"; $cmds['MoveUp'] = $cmds['MoveRoot'].'Up';
$cmds['MoveDown'] = $cmds['MoveRoot']."Down"; $cmds['MoveDown'] = $cmds['MoveRoot'].'Down';
$cmds['MoveLeft'] = $cmds['MoveRoot']."Left"; $cmds['MoveLeft'] = $cmds['MoveRoot'].'Left';
$cmds['MoveRight'] = $cmds['MoveRoot']."Right"; $cmds['MoveRight'] = $cmds['MoveRoot'].'Right';
$cmds['MoveUpLeft'] = $cmds['MoveRoot']."UpLeft"; $cmds['MoveUpLeft'] = $cmds['MoveRoot'].'UpLeft';
$cmds['MoveUpRight'] = $cmds['MoveRoot']."UpRight"; $cmds['MoveUpRight'] = $cmds['MoveRoot'].'UpRight';
$cmds['MoveDownLeft'] = $cmds['MoveRoot']."DownLeft"; $cmds['MoveDownLeft'] = $cmds['MoveRoot'].'DownLeft';
$cmds['MoveDownRight'] = $cmds['MoveRoot']."DownRight"; $cmds['MoveDownRight'] = $cmds['MoveRoot'].'DownRight';
} }
return( $cmds ); return( $cmds );
} }
@ -128,15 +128,15 @@ function controlFocus( $monitor, $cmds ) {
?> ?>
<div class="arrowControl focusControls"> <div class="arrowControl focusControls">
<div class="arrowLabel"><?php echo translate('Near') ?></div> <div class="arrowLabel"><?php echo translate('Near') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['FocusNear'] ?>',event,0,-1)"></div> <button type="button" class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['FocusNear'] ?>',event,0,-1)"></button>
<div class="arrowCenter"<?php if ( $monitor->CanFocusCon() ) { ?> onclick="controlCmd('<?php echo $cmds['FocusStop'] ?>')"<?php } ?>><?php echo translate('Focus') ?></div> <button type="button" class="arrowCenter"<?php if ( $monitor->CanFocusCon() ) { ?> onclick="controlCmd('<?php echo $cmds['FocusStop'] ?>')"<?php } ?>><?php echo translate('Focus') ?></button>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['FocusFar'] ?>',event,0,1)"></div> <button type="button" class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['FocusFar'] ?>',event,0,1)"></button>
<div class="arrowLabel"><?php echo translate('Far') ?></div> <div class="arrowLabel"><?php echo translate('Far') ?></div>
<?php <?php
if ( $monitor->CanAutoFocus() ) { if ( $monitor->CanAutoFocus() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['FocusAuto'] ?>')"/> <button type="button" class="ptzTextBtn" value="<?php echo $cmds['FocusAuto'] ?>" onclick="controlCmd('<?php echo $cmds['FocusAuto'] ?>')"><?php echo translate('Auto') ?></button>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Man') ?>" onclick="controlCmd('<?php echo $cmds['FocusMan'] ?>')"/> <button type="button" class="ptzTextBtn" value="<?php echo $cmds['FocusMan'] ?>" onclick="controlCmd('<?php echo $cmds['FocusMan'] ?>')"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -152,15 +152,15 @@ function controlZoom( $monitor, $cmds ) {
?> ?>
<div class="arrowControl zoomControls"> <div class="arrowControl zoomControls">
<div class="arrowLabel"><?php echo translate('Tele') ?></div> <div class="arrowLabel"><?php echo translate('Tele') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['ZoomTele'] ?>',event,0,-1)"></div> <button type="button" class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['ZoomTele'] ?>',event,0,-1)"></button>
<div class="arrowCenter"<?php if ( $monitor->CanZoomCon() ) { ?> onclick="controlCmd('<?php echo $cmds['ZoomStop'] ?>')"<?php } ?>><?php echo translate('Zoom') ?></div> <button type="button" class="arrowCenter"<?php if ( $monitor->CanZoomCon() ) { ?> onclick="controlCmd('<?php echo $cmds['ZoomStop'] ?>')"<?php } ?>><?php echo translate('Zoom') ?></button>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['ZoomWide'] ?>',event,0,1)"></div> <button type="button" class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['ZoomWide'] ?>',event,0,1)"></button>
<div class="arrowLabel"><?php echo translate('Wide') ?></div> <div class="arrowLabel"><?php echo translate('Wide') ?></div>
<?php <?php
if ( $monitor->CanAutoZoom() ) { if ( $monitor->CanAutoZoom() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['ZoomAuto'] ?>')"/> <button type="button" class="ptzTextBtn" value="Auto" onclick="controlCmd('<?php echo $cmds['ZoomAuto'] ?>')"><?php echo translate('Auto') ?></button>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Man') ?>" onclick="controlCmd('<?php echo $cmds['ZoomMan'] ?>')"/> <button type="button" class="ptzTextBtn" value="Man" onclick="controlCmd('<?php echo $cmds['ZoomMan'] ?>')"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -175,15 +175,15 @@ function controlIris( $monitor, $cmds ) {
?> ?>
<div class="arrowControl irisControls"> <div class="arrowControl irisControls">
<div class="arrowLabel"><?php echo translate('Open') ?></div> <div class="arrowLabel"><?php echo translate('Open') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['IrisOpen'] ?>',event,0,-1)"></div> <button type="button" class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['IrisOpen'] ?>',event,0,-1)"></button>
<div class="arrowCenter"<?php if ( $monitor->CanIrisCon() ) { ?> onclick="controlCmd('<?php echo $cmds['IrisStop'] ?>')"<?php } ?>><?php echo translate('Iris') ?></div> <button type="button" class="arrowCenter"<?php if ( $monitor->CanIrisCon() ) { ?> onclick="controlCmd('<?php echo $cmds['IrisStop'] ?>')"<?php } ?>><?php echo translate('Iris') ?></button>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['IrisClose'] ?>',event,0,1)"></div> <button type="button" class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['IrisClose'] ?>',event,0,1)"></button>
<div class="arrowLabel"><?php echo translate('Close') ?></div> <div class="arrowLabel"><?php echo translate('Close') ?></div>
<?php <?php
if ( $monitor->CanAutoIris() ) { if ( $monitor->CanAutoIris() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['IrisAuto'] ?>')"/> <button type="button" class="ptzTextBtn" value="Auto" onclick="controlCmd('<?php echo $cmds['IrisAuto'] ?>')"><?php echo translate('Auto') ?></button>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Man') ?>" onclick="controlCmd('<?php echo $cmds['IrisMan'] ?>')"/> <button type="button" class="ptzTextBtn" value="Man" onclick="controlCmd('<?php echo $cmds['IrisMan'] ?>')"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -199,15 +199,15 @@ function controlWhite( $monitor, $cmds ) {
?> ?>
<div class="arrowControl whiteControls"> <div class="arrowControl whiteControls">
<div class="arrowLabel"><?php echo translate('In') ?></div> <div class="arrowLabel"><?php echo translate('In') ?></div>
<div class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['WhiteIn'] ?>',event,0,-1)"></div> <button type="button" class="longArrowBtn upBtn" onclick="controlCmd('<?php echo $cmds['WhiteIn'] ?>',event,0,-1)"></button>
<div class="arrowCenter"<?php if ( $monitor->CanWhiteCon() ) { ?> onclick="controlCmd('<?php echo $cmds['WhiteStop'] ?>')"<?php } ?>><?php echo translate('White') ?></div> <button type="button" class="arrowCenter"<?php if ( $monitor->CanWhiteCon() ) { ?> onclick="controlCmd('<?php echo $cmds['WhiteStop'] ?>')"<?php } ?>><?php echo translate('White') ?></button>
<div class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['WhiteOut'] ?>',event,0,1)"></div> <button type="button" class="longArrowBtn downBtn" onclick="controlCmd('<?php echo $cmds['WhiteOut'] ?>',event,0,1)"></button>
<div class="arrowLabel"><?php echo translate('Out') ?></div> <div class="arrowLabel"><?php echo translate('Out') ?></div>
<?php <?php
if ( $monitor->CanAutoWhite() ) { if ( $monitor->CanAutoWhite() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Auto') ?>" onclick="controlCmd('<?php echo $cmds['WhiteAuto'] ?>')"/> <button type="button" class="ptzTextBtn" value="Auto" onclick="controlCmd('<?php echo $cmds['WhiteAuto'] ?>')"><?php echo translate('Auto') ?></button>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Man') ?>" onclick="controlCmd('<?php echo $cmds['WhiteMan'] ?>')"/> <button type="button" class="ptzTextBtn" value="Man" onclick="controlCmd('<?php echo $cmds['WhiteMan'] ?>')"><?php echo translate('Man') ?></button>
<?php <?php
} }
?> ?>
@ -229,19 +229,19 @@ function controlPanTilt( $monitor, $cmds ) {
$hasTilt = $monitor->CanTilt(); $hasTilt = $monitor->CanTilt();
$hasDiag = $hasPan && $hasTilt && $monitor->CanMoveDiag(); $hasDiag = $hasPan && $hasTilt && $monitor->CanMoveDiag();
?> ?>
<div class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpLeft'] ?>',event,-1,-1)"></div> <button type="button" class="arrowBtn upLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpLeft'] ?>',event,-1,-1)"></button>
<div class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUp'] ?>',event,0,-1)"></div> <button type="button" class="arrowBtn upBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUp'] ?>',event,0,-1)"></button>
<div class="arrowBtn upRightBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpRight'] ?>',event,1,-1)"></div> <button type="button" class="arrowBtn upRightBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveUpRight'] ?>',event,1,-1)"></button>
<div class="arrowBtn leftBtn<?php echo $hasPan?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveLeft'] ?>',event,1,0)"></div> <button type="button" class="arrowBtn leftBtn<?php echo $hasPan?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveLeft'] ?>',event,1,0)"></button>
<?php if ( isset($cmds['Center']) ) { ?> <?php if ( isset($cmds['Center']) ) { ?>
<div class="arrowBtn centerBtn" onclick="controlCmd('<?php echo $cmds['Center'] ?>')"></div> <button type="button" class="arrowBtn centerBtn" onclick="controlCmd('<?php echo $cmds['Center'] ?>')"></button>
<?php } else { ?> <?php } else { ?>
<div class="arrowBtn NocenterBtn"></div> <button type="button" class="arrowBtn NocenterBtn"></button>
<?php } ?> <?php } ?>
<div class="arrowBtn rightBtn<?php echo $hasPan?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveRight'] ?>',event,1,0)"></div> <button type="button" class="arrowBtn rightBtn<?php echo $hasPan?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveRight'] ?>',event,1,0)"></button>
<div class="arrowBtn downLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveDownLeft'] ?>',event,-1,1)"></div> <button type="button" class="arrowBtn downLeftBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveDownLeft'] ?>',event,-1,1)"></button>
<div class="arrowBtn downBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveDown'] ?>',event,0,1)"></div> <button type="button" class="arrowBtn downBtn<?php echo $hasTilt?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveDown'] ?>',event,0,1)"></button>
<div class="arrowBtn downRightBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveDownRight'] ?>',event,1,1)"></div> <button type="button" class="arrowBtn downRightBtn<?php echo $hasDiag?'':' invisible' ?>" onclick="controlCmd('<?php echo $cmds['MoveDownRight'] ?>',event,1,1)"></button>
</div> </div>
</div> </div>
<?php <?php
@ -270,7 +270,7 @@ function controlPresets( $monitor, $cmds ) {
<?php <?php
for ( $i = 1; $i <= $monitor->NumPresets(); $i++ ) { for ( $i = 1; $i <= $monitor->NumPresets(); $i++ ) {
?> ?>
<input type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?$labels[$i]:"" ?>" value="<?php echo $i ?>" onclick="controlCmd('<?php echo $cmds['PresetGoto'] ?><?php echo $i ?>');"/> <button type="button" class="ptzNumBtn" title="<?php echo isset($labels[$i])?htmlentities($labels[$i]):'' ?>" value="<?php echo $i ?>" onclick="controlCmd('<?php echo $cmds['PresetGoto'] ?><?php echo $i ?>');"/><?php echo $i ?></button>
<?php <?php
if ( $i && (($i%$presetBreak) == 0) ) { if ( $i && (($i%$presetBreak) == 0) ) {
?><br/><?php ?><br/><?php
@ -282,12 +282,12 @@ function controlPresets( $monitor, $cmds ) {
<?php <?php
if ( $monitor->HasHomePreset() ) { if ( $monitor->HasHomePreset() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Home') ?>" onclick="controlCmd('<?php echo $cmds['PresetHome'] ?>');"/> <button type="button" class="ptzTextBtn" value="<?php echo translate('Home') ?>" onclick="controlCmd('<?php echo $cmds['PresetHome'] ?>');"/>
<?php <?php
} }
if ( canEdit('Monitors') && $monitor->CanSetPresets() ) { if ( canEdit('Monitors') && $monitor->CanSetPresets() ) {
?> ?>
<input type="button" class="ptzTextBtn popup-link" value="<?php echo translate('Set') ?>" data-url="?view=controlpreset&amp;mid=<?php echo $monitor->Id() ?>" data-window-name="zmPreset" data-window-tag="preset"/> <button type="button" class="ptzTextBtn popup-link" value="<?php echo translate('Set') ?>" data-url="?view=controlpreset&amp;mid=<?php echo $monitor->Id() ?>" data-window-name="zmPreset" data-window-tag="preset"/>
<?php <?php
} }
?> ?>
@ -308,17 +308,17 @@ function controlPower( $monitor, $cmds ) {
<?php <?php
if ( $monitor->CanWake() ) { if ( $monitor->CanWake() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Wake') ?>" onclick="controlCmd('<?php echo $cmds['Wake'] ?>')"/> <button type="button" class="ptzTextBtn" value="Wake" onclick="controlCmd('<?php echo $cmds['Wake'] ?>')"><?php echo translate('Wake') ?></button>
<?php <?php
} }
if ( $monitor->CanSleep() ) { if ( $monitor->CanSleep() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Sleep') ?>" onclick="controlCmd('<?php echo $cmds['Sleep'] ?>')"/> <button type="button" class="ptzTextBtn" value="Sleep" onclick="controlCmd('<?php echo $cmds['Sleep'] ?>')"><?php echo translate('Sleep') ?></button>
<?php <?php
} }
if ( $monitor->CanReset() ) { if ( $monitor->CanReset() ) {
?> ?>
<input type="button" class="ptzTextBtn" value="<?php echo translate('Reset') ?>" onclick="controlCmd('<?php echo $cmds['Reset'] ?>')"/> <button type="button" class="ptzTextBtn" value="Reset" onclick="controlCmd('<?php echo $cmds['Reset'] ?>')"><?php echo translate('Reset') ?></button>
<?php <?php
} }
?> ?>

View File

@ -57,7 +57,7 @@ function xhtmlHeaders( $file, $title ) {
<head> <head>
<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">
<title><?php echo ZM_WEB_TITLE_PREFIX ?> - <?php echo validHtmlStr($title) ?></title> <title><?php echo validHtmlStr(ZM_WEB_TITLE_PREFIX); ?> - <?php echo 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 "
@ -100,11 +100,9 @@ echo output_link_if_exists( array(
if ( $viewCssPhpFile ) { if ( $viewCssPhpFile ) {
?> ?>
<style type="text/css"> <style type="text/css">
/*<![CDATA[*/
<?php <?php
require_once($viewCssPhpFile); require_once($viewCssPhpFile);
?> ?>
/*]]>*/
</style> </style>
<?php <?php
} }
@ -207,7 +205,7 @@ function getBodyTopHTML() {
<body> <body>
<noscript> <noscript>
<div style="background-color:red;color:white;font-size:x-large;"> <div style="background-color:red;color:white;font-size:x-large;">
'. ZM_WEB_TITLE .' requires Javascript. Please enable Javascript in your browser for this site. '. validHtmlStr(ZM_WEB_TITLE) .' requires Javascript. Please enable Javascript in your browser for this site.
</div> </div>
</noscript> </noscript>
@ -219,7 +217,7 @@ function getBodyTopHTML() {
} // end function getBodyTopHTML } // end function getBodyTopHTML
function getNavBarHTML($reload = null) { function getNavBarHTML($reload = null) {
# Provide a facility to turn off the headers if you put headers=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 '';
@ -254,27 +252,29 @@ function getNavBarHTML($reload = null) {
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<div class="navbar-brand"><a href="<?php echo ZM_HOME_URL?>" target="<?php echo ZM_WEB_TITLE ?>"><?php echo ZM_HOME_CONTENT ?></a></div> <div class="navbar-brand"><a href="<?php echo validHtmlStr(ZM_HOME_URL); ?>" target="<?php echo validHtmlStr(ZM_WEB_TITLE); ?>"><?php echo ZM_HOME_CONTENT ?></a></div>
</div> </div>
<div class="collapse navbar-collapse" id="main-header-nav"> <div class="collapse navbar-collapse" id="main-header-nav">
<?php if ( canView('Monitors') ) { ?>
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<?php if ( $user and $user['Username'] ) { ?>
<?php if ( canView('Monitors') ) { ?>
<li><a href="?view=console"><?php echo translate('Console') ?></a></li> <li><a href="?view=console"><?php echo translate('Console') ?></a></li>
<?php } // end if canView('Monitors') ?>
<?php if ( canView('System') ) { ?> <?php if ( canView('System') ) { ?>
<li><a href="?view=options"><?php echo translate('Options') ?></a></li> <li><a href="?view=options"><?php echo translate('Options') ?></a></li>
<li> <li>
<?php <?php
if ( logToDatabase() > Logger::NOLOG ) { if ( ZM\logToDatabase() > ZM\Logger::NOLOG ) {
if ( ! ZM_RUN_AUDIT ) { if ( ! ZM_RUN_AUDIT ) {
# zmaudit can clean the logs, but if we aren't running it, then we should clecan them regularly # zmaudit can clean the logs, but if we aren't running it, then we should clecan them regularly
dbQuery('DELETE FROM Logs WHERE TimeKey < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100'); dbQuery('DELETE FROM Logs WHERE TimeKey < unix_timestamp( NOW() - interval '.ZM_LOG_DATABASE_LIMIT.') LIMIT 100');
} }
echo makePopupLink( '?view=log', 'zmLog', 'log', '<span class="'.logState().'">'.translate('Log').'</span>' ); echo makePopupLink( '?view=log', 'zmLog', 'log', '<span class="'.logState().'">'.translate('Log').'</span>' );
} }
} // end if canview(System)
?></li> ?></li>
<?php <?php
} // end if canview(System)
if ( ZM_OPT_X10 && canView('Devices') ) { ?> if ( ZM_OPT_X10 && canView('Devices') ) { ?>
<li><a href="?view=devices">Devices</a></li> <li><a href="?view=devices">Devices</a></li>
<?php } ?> <?php } ?>
@ -295,7 +295,7 @@ if (isset($_REQUEST['filter']['Query']['terms']['attr'])) {
$terms = $_REQUEST['filter']['Query']['terms']; $terms = $_REQUEST['filter']['Query']['terms'];
$count = 0; $count = 0;
foreach ($terms as $term) { foreach ($terms as $term) {
if ($term['attr'] == "StartDateTime") { if ( $term['attr'] == 'StartDateTime' ) {
$count += 1; $count += 1;
if ($term['op'] == '>=') $minTime = $term['val']; if ($term['op'] == '>=') $minTime = $term['val'];
if ($term['op'] == '<=') $maxTime = $term['val']; if ($term['op'] == '<=') $maxTime = $term['val'];
@ -314,7 +314,6 @@ if (isset($_REQUEST['filter']['Query']['terms']['attr'])) {
<li><a href="?view=report_event_audit"<?php echo $view=='report_event_audit'?' class="selected"':''?>><?php echo translate('ReportEventAudit') ?></a></li> <li><a href="?view=report_event_audit"<?php echo $view=='report_event_audit'?' class="selected"':''?>><?php echo translate('ReportEventAudit') ?></a></li>
<li><a href="#"><span id="flip" class="glyphicon glyphicon-menu-<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down') ? 'down' : 'up' ?> pull-right"></span></a></li> <li><a href="#"><span id="flip" class="glyphicon glyphicon-menu-<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down') ? 'down' : 'up' ?> pull-right"></span></a></li>
</ul> </ul>
<?php } // end if canView('Monitors') ?>
<div class="navbar-right"> <div class="navbar-right">
<?php if ( ZM_OPT_USE_AUTH and $user ) { ?> <?php if ( ZM_OPT_USE_AUTH and $user ) { ?>
@ -328,6 +327,7 @@ if (isset($_REQUEST['filter']['Query']['terms']['attr'])) {
<p class="navbar-text"> <?php echo $status ?></p> <p class="navbar-text"> <?php echo $status ?></p>
<?php } ?> <?php } ?>
</div> </div>
<?php } # end if !$user or $user['Id'] meaning logged in ?>
</div><!-- End .navbar-collapse --> </div><!-- End .navbar-collapse -->
</div> <!-- End .container-fluid --> </div> <!-- End .container-fluid -->
<div id="panel"<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down' ) ? 'style="display:none;"' : '' ?>> <div id="panel"<?php echo ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down' ) ? 'style="display:none;"' : '' ?>>
@ -355,20 +355,20 @@ if ($reload == 'reload') ob_start();
?> ?>
<li><?php echo translate('Storage') ?>: <li><?php echo translate('Storage') ?>:
<?php <?php
$storage_areas = Storage::find(); $storage_areas = ZM\Storage::find();
$storage_paths = null; $storage_paths = null;
foreach ( $storage_areas as $area ) { foreach ( $storage_areas as $area ) {
$storage_paths[$area->Path()] = $area; $storage_paths[$area->Path()] = $area;
} }
if ( ! isset($storage_paths[ZM_DIR_EVENTS]) ) { if ( ! isset($storage_paths[ZM_DIR_EVENTS]) ) {
array_push( $storage_areas, new Storage() ); array_push( $storage_areas, new ZM\Storage() );
} }
$func = function($S){ $func = function($S){
$class = ''; $class = '';
if ( $S->disk_usage_percent() > 98 ) { if ( $S->disk_usage_percent() > 98 ) {
$class = "error"; $class = 'error';
} else if ( $S->disk_usage_percent() > 90 ) { } else if ( $S->disk_usage_percent() > 90 ) {
$class = "warning"; $class = 'warning';
} }
$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' : '' );
@ -383,7 +383,7 @@ if ($reload == 'reload') ob_start();
?></li> ?></li>
</ul> </ul>
<?php if ( defined('ZM_WEB_CONSOLE_BANNER') and ZM_WEB_CONSOLE_BANNER != '' ) { ?> <?php if ( defined('ZM_WEB_CONSOLE_BANNER') and ZM_WEB_CONSOLE_BANNER != '' ) { ?>
<h3 id="development"><?php echo ZM_WEB_CONSOLE_BANNER ?></h3> <h3 id="development"><?php echo validHtmlStr(ZM_WEB_CONSOLE_BANNER); ?></h3>
<?php } ?> <?php } ?>
<!-- End .footer/reload --></div> <!-- End .footer/reload --></div>
<?php <?php

View File

@ -27,7 +27,7 @@
var popupSizes = { var popupSizes = {
'bandwidth': {'width': 300, 'height': 200}, 'bandwidth': {'width': 300, 'height': 200},
'console': {'width': 750, 'height': 312}, 'console': {'width': 750, 'height': 312},
'control': {'width': 380, 'height': 480}, 'control': {'width': 480, 'height': 480},
'controlcaps': {'width': 780, 'height': 320}, 'controlcaps': {'width': 780, 'height': 320},
'controlcap': {'width': 400, 'height': 400}, 'controlcap': {'width': 400, 'height': 400},
'cycle': {'addWidth': 32, 'minWidth': 384, 'addHeight': 62}, 'cycle': {'addWidth': 32, 'minWidth': 384, 'addHeight': 62},

View File

@ -126,6 +126,11 @@ function createPopup( url, name, tag, width, height ) {
} }
} }
// Polyfill for NodeList.prototype.forEach on IE.
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = Array.prototype.forEach;
}
window.addEventListener("DOMContentLoaded", function onSkinDCL() { window.addEventListener("DOMContentLoaded", function onSkinDCL() {
document.querySelectorAll("form.validateFormOnSubmit").forEach(function(el) { document.querySelectorAll("form.validateFormOnSubmit").forEach(function(el) {
el.addEventListener("submit", function onSubmit(evt) { el.addEventListener("submit", function onSubmit(evt) {
@ -150,8 +155,8 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
var tag = el.getAttribute("data-window-tag"); var tag = el.getAttribute("data-window-tag");
var width = el.getAttribute("data-window-width"); var width = el.getAttribute("data-window-width");
var height = el.getAttribute("data-window-height"); var height = el.getAttribute("data-window-height");
createPopup(url, name, tag, width, height);
evt.preventDefault(); evt.preventDefault();
createPopup(url, name, tag, width, height);
}); });
}); });
@ -173,6 +178,14 @@ window.addEventListener("DOMContentLoaded", function onSkinDCL() {
}; };
}); });
// 'data-on-click-true' calls the global function in the attribute value with no arguments when a click happens.
document.querySelectorAll("a[data-on-click-true], button[data-on-click-true], input[data-on-click-true]").forEach(function attachOnClick(el) {
var fnName = el.getAttribute("data-on-click-true");
el.onclick = function() {
window[fnName](true);
};
});
// 'data-on-change-this' calls the global function in the attribute value with the element when a change happens. // 'data-on-change-this' calls the global function in the attribute value with the element when a change happens.
document.querySelectorAll("select[data-on-change-this], input[data-on-change-this]").forEach(function attachOnChangeThis(el) { document.querySelectorAll("select[data-on-change-this], input[data-on-change-this]").forEach(function attachOnChangeThis(el) {
var fnName = el.getAttribute("data-on-change-this"); var fnName = el.getAttribute("data-on-change-this");

View File

@ -29,7 +29,11 @@ var AJAX_TIMEOUT = <?php echo ZM_WEB_AJAX_TIMEOUT ?>;
var navBarRefresh = <?php echo 1000*ZM_WEB_REFRESH_NAVBAR ?>; var navBarRefresh = <?php echo 1000*ZM_WEB_REFRESH_NAVBAR ?>;
var currentView = '<?php echo $view ?>'; var currentView = '<?php echo $view ?>';
var thisUrl = '<?php echo ZM_BASE_URL.$_SERVER['PHP_SELF'] ?>'; <?php
/* We can't trust PHP_SELF on a path like /index.php/"%3E%3Cimg src=x onerror=prompt('1');%3E which
will still load index.php but will include the arbitrary payload after `.php/`. To mitigate this,
try to avoid using PHP_SELF but here I try to replace everything after '.php'. */ ?>
var thisUrl = '<?php echo ZM_BASE_URL.preg_replace('/\.php.*$/i', '.php', $_SERVER['PHP_SELF']) ?>';
var skinPath = '<?php echo ZM_SKIN_PATH ?>'; var skinPath = '<?php echo ZM_SKIN_PATH ?>';
var serverId = '<?php echo defined('ZM_SERVER_ID') ? ZM_SERVER_ID : '' ?>'; var serverId = '<?php echo defined('ZM_SERVER_ID') ? ZM_SERVER_ID : '' ?>';

View File

@ -18,7 +18,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// //
$servers = Server::find(null, array('order'=>'lower(Name)')); $servers = ZM\Server::find(null, array('order'=>'lower(Name)'));
$ServersById = array(); $ServersById = array();
foreach ( $servers as $S ) { foreach ( $servers as $S ) {
$ServersById[$S->Id()] = $S; $ServersById[$S->Id()] = $S;
@ -37,7 +37,7 @@ foreach ( array('Group','Function','ServerId','StorageId','Status','MonitorId','
} }
session_write_close(); session_write_close();
$storage_areas = Storage::find(); $storage_areas = ZM\Storage::find();
$StorageById = array(); $StorageById = array();
foreach ( $storage_areas as $S ) { foreach ( $storage_areas as $S ) {
$StorageById[$S->Id()] = $S; $StorageById[$S->Id()] = $S;
@ -52,7 +52,7 @@ $html =
'; ';
$GroupsById = array(); $GroupsById = array();
foreach ( Group::find() as $G ) { foreach ( ZM\Group::find() as $G ) {
$GroupsById[$G->Id()] = $G; $GroupsById[$G->Id()] = $G;
} }
@ -61,14 +61,13 @@ if ( count($GroupsById) ) {
$html .= '<span id="groupControl"><label>'. translate('Group') .'</label>'; $html .= '<span id="groupControl"><label>'. translate('Group') .'</label>';
# This will end up with the group_id of the deepest selection # This will end up with the group_id of the deepest selection
$group_id = isset($_SESSION['Group']) ? $_SESSION['Group'] : null; $group_id = isset($_SESSION['Group']) ? $_SESSION['Group'] : null;
$html .= Group::get_group_dropdown(); $html .= ZM\Group::get_group_dropdown();
$groupSql = Group::get_group_sql($group_id); $groupSql = ZM\Group::get_group_sql($group_id);
$html .= '</span>'; $html .= '</span>';
} }
$selected_monitor_ids = isset($_SESSION['MonitorId']) ? $_SESSION['MonitorId'] : array(); $selected_monitor_ids = isset($_SESSION['MonitorId']) ? $_SESSION['MonitorId'] : array();
if ( ! is_array( $selected_monitor_ids ) ) { if ( ! is_array( $selected_monitor_ids ) ) {
Warning("Turning selected_monitor_ids into an array $selected_monitor_ids");
$selected_monitor_ids = array($selected_monitor_ids); $selected_monitor_ids = array($selected_monitor_ids);
} }
@ -95,7 +94,7 @@ if ( ! empty($user['MonitorIds']) ) {
} }
$html .= '<span class="MonitorNameFilter"><label>'.translate('Name').'</label>'; $html .= '<span class="MonitorNameFilter"><label>'.translate('Name').'</label>';
$html .= '<input type="text" name="MonitorName" value="'.(isset($_SESSION['MonitorName'])?$_SESSION['MonitorName']:'').'" placeholder="text or regular expression"/>'; $html .= '<input type="text" name="MonitorName" value="'.(isset($_SESSION['MonitorName'])?validHtmlStr($_SESSION['MonitorName']):'').'" placeholder="text or regular expression"/>';
$html .= '</span>'; $html .= '</span>';
$Functions = array(); $Functions = array();
@ -160,7 +159,7 @@ $html .= htmlSelect( 'Status[]', $status_options,
$html .= '</span>'; $html .= '</span>';
$html .= '<span class="SourceFilter"><label>'.translate('Source').'</label>'; $html .= '<span class="SourceFilter"><label>'.translate('Source').'</label>';
$html .= '<input type="text" name="Source" value="'.(isset($_SESSION['Source'])?$_SESSION['Source']:'').'" placeholder="text or regular expression"/>'; $html .= '<input type="text" name="Source" value="'.(isset($_SESSION['Source'])?validHtmlStr($_SESSION['Source']):'').'" placeholder="text or regular expression"/>';
$html .= '</span>'; $html .= '</span>';
$sql = 'SELECT *,S.Status AS Status, S.CaptureFPS AS CaptureFPS, S.AnalysisFPS AS AnalysisFPS, S.CaptureBandwidth AS CaptureBandwidth $sql = 'SELECT *,S.Status AS Status, S.CaptureFPS AS CaptureFPS, S.AnalysisFPS AS AnalysisFPS, S.CaptureBandwidth AS CaptureBandwidth
@ -189,12 +188,12 @@ $html .= htmlSelect( 'Status[]', $status_options,
for ( $i = 0; $i < count($monitors); $i++ ) { for ( $i = 0; $i < count($monitors); $i++ ) {
if ( !visibleMonitor($monitors[$i]['Id']) ) { if ( !visibleMonitor($monitors[$i]['Id']) ) {
Warning('Monitor '.$monitors[$i]['Id'].' is not visible'); ZM\Logger::Warning('Monitor '.$monitors[$i]['Id'].' is not visible');
continue; continue;
} }
if ( isset($_SESSION['MonitorName']) ) { if ( isset($_SESSION['MonitorName']) ) {
$Monitor = new Monitor($monitors[$i]); $Monitor = new ZM\Monitor($monitors[$i]);
ini_set('track_errors', 'on'); ini_set('track_errors', 'on');
$php_errormsg = ''; $php_errormsg = '';
$regexp = $_SESSION['MonitorName']; $regexp = $_SESSION['MonitorName'];
@ -210,7 +209,7 @@ $html .= htmlSelect( 'Status[]', $status_options,
} }
if ( isset($_SESSION['Source']) ) { if ( isset($_SESSION['Source']) ) {
$Monitor = new Monitor($monitors[$i]); $Monitor = new ZM\Monitor($monitors[$i]);
ini_set('track_errors', 'on'); ini_set('track_errors', 'on');
$php_errormsg = ''; $php_errormsg = '';
$regexp = $_SESSION['Source']; $regexp = $_SESSION['Source'];

View File

@ -33,7 +33,7 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
<?php echo $navbar ?> <?php echo $navbar ?>
<div id="content"> <div id="content">
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>"> <form name="contentForm" id="contentForm" method="post" action="?">
<div style="position:relative;"> <div style="position:relative;">
<div id="results" style="position: absolute; top:0; right: 0; width: 50%; height: 100%;"> <div id="results" style="position: absolute; top:0; right: 0; width: 50%; height: 100%;">
<fieldset><legend>Results</legend> <fieldset><legend>Results</legend>
@ -61,8 +61,8 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
<th>Group</th> <th>Group</th>
</tr> </tr>
<tr title="Example Data"> <tr title="Example Data">
<td>Example Name MN1-30 INQ37.01</td> <td>Example Name Driveway</td>
<td>http://10.34.152.20:2001/?action=stream</td> <td>http://192.168.1.0/?action=stream</td>
<td>MN1</td> <td>MN1</td>
</tr> </tr>
</table> </table>
@ -80,7 +80,7 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
?> ?>
</td></tr> </td></tr>
<?php <?php
$servers = Server::find(); $servers = ZM\Server::find();
$ServersById = array(); $ServersById = array();
foreach ( $servers as $S ) { foreach ( $servers as $S ) {
$ServersById[$S->Id()] = $S; $ServersById[$S->Id()] = $S;
@ -92,7 +92,7 @@ xhtmlHeaders(__FILE__, translate('AddMonitors'));
</td></tr> </td></tr>
<?php <?php
} }
$storage_areas = Storage::find(); $storage_areas = ZM\Storage::find();
$StorageById = array(); $StorageById = array();
foreach ( $storage_areas as $S ) { foreach ( $storage_areas as $S ) {
$StorageById[$S->Id()] = $S; $StorageById[$S->Id()] = $S;

View File

@ -43,8 +43,8 @@ xhtmlHeaders(__FILE__, translate('Bandwidth') );
<h2><?php echo translate('Bandwidth') ?></h2> <h2><?php echo translate('Bandwidth') ?></h2>
</div> </div>
<div id="content"> <div id="content">
<form name="contentForm" id="contentForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>"> <form name="contentForm" id="contentForm" method="get" action="?">
<input type="hidden" name="view" value="none"/> <input type="hidden" name="view" value="bandwidth"/>
<input type="hidden" name="action" value="bandwidth"/> <input type="hidden" name="action" value="bandwidth"/>
<p><?php echo translate('SetNewBandwidth') ?></p> <p><?php echo translate('SetNewBandwidth') ?></p>
<p><?php echo buildSelect( "newBandwidth", $bandwidth_options ) ?></p> <p><?php echo buildSelect( "newBandwidth", $bandwidth_options ) ?></p>

View File

@ -160,7 +160,7 @@ if ( $show_storage_areas ) $left_columns += 1;
xhtmlHeaders( __FILE__, translate('Console') ); xhtmlHeaders( __FILE__, translate('Console') );
getBodyTopHTML(); getBodyTopHTML();
?> ?>
<form name="monitorForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>"> <form name="monitorForm" method="get" action="?">
<input type="hidden" name="view" value="<?php echo $view ?>"/> <input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value=""/> <input type="hidden" name="action" value=""/>
@ -230,7 +230,7 @@ ob_end_clean();
echo $table_head; echo $table_head;
for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) { for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
$monitor = $displayMonitors[$monitor_i]; $monitor = $displayMonitors[$monitor_i];
$Monitor = new Monitor($monitor); $Monitor = new ZM\Monitor($monitor);
if ( $monitor_i and ( $monitor_i % 100 == 0 ) ) { if ( $monitor_i and ( $monitor_i % 100 == 0 ) ) {
echo '</table>'; echo '</table>';
@ -275,12 +275,12 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
<span class="glyphicon glyphicon-dot <?php echo $dot_class ?>" aria-hidden="true"></span><a <?php echo ($stream_available ? 'href="?view=watch&amp;mid='.$monitor['Id'].'">' : '>') . $monitor['Name'] ?></a><br/><div class="small text-nowrap text-muted"> <span class="glyphicon glyphicon-dot <?php echo $dot_class ?>" aria-hidden="true"></span><a <?php echo ($stream_available ? 'href="?view=watch&amp;mid='.$monitor['Id'].'">' : '>') . $monitor['Name'] ?></a><br/><div class="small text-nowrap text-muted">
<?php echo implode('<br/>', <?php echo implode('<br/>',
array_map(function($group_id){ array_map(function($group_id){
$Group = Group::find_one(array('Id'=>$group_id)); $Group = ZM\Group::find_one(array('Id'=>$group_id));
if ( $Group ) { if ( $Group ) {
$Groups = $Group->Parents(); $Groups = $Group->Parents();
array_push( $Groups, $Group ); array_push( $Groups, $Group );
} }
return implode(' &gt; ', array_map(function($Group){ return '<a href="'. ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=montagereview&amp;GroupId='.$Group->Id().'">'.$Group->Name().'</a>'; }, $Groups )); return implode(' &gt; ', array_map(function($Group){ return '<a href="?view=montagereview&amp;GroupId='.$Group->Id().'">'.$Group->Name().'</a>'; }, $Groups ));
}, $Monitor->GroupIds() ) ); }, $Monitor->GroupIds() ) );
?> ?>
</div></td> </div></td>
@ -305,10 +305,10 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
</div></td> </div></td>
<?php <?php
if ( count($servers) ) { ?> if ( count($servers) ) { ?>
<td class="colServer"><?php $Server = isset($ServersById[$monitor['ServerId']]) ? $ServersById[$monitor['ServerId']] : new Server( $monitor['ServerId'] ); echo $Server->Name(); ?></td> <td class="colServer"><?php $Server = isset($ServersById[$monitor['ServerId']]) ? $ServersById[$monitor['ServerId']] : new ZM\Server($monitor['ServerId']); echo $Server->Name(); ?></td>
<?php <?php
} }
echo '<td class="colSource">'. makePopupLink( '?view=monitor&amp;mid='.$monitor['Id'], 'zmMonitor'.$monitor['Id'], 'monitor', '<span class="'.$source_class.'">'.$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 $StorageById[ $monitor['StorageId'] ]->Name(); } ?></td> <td class="colStorage"><?php if ( isset($StorageById[$monitor['StorageId']]) ) { echo $StorageById[ $monitor['StorageId'] ]->Name(); } ?></td>

View File

@ -26,8 +26,8 @@ if ( !canView( 'Control' ) ) {
$params = array(); $params = array();
$groupSql = ''; $groupSql = '';
if ( !empty($_REQUEST['group']) ) { if ( !empty($_REQUEST['group']) ) {
$groupSql = " AND gm.GroupId = :groupid"; $groupSql = ' AND gm.GroupId = :groupid';
$params[":groupid"] = $_REQUEST['group']; $params[':groupid'] = $_REQUEST['group'];
} }
$mid = !empty($_REQUEST['mid']) ? validInt($_REQUEST['mid']) : 0; $mid = !empty($_REQUEST['mid']) ? validInt($_REQUEST['mid']) : 0;
@ -46,7 +46,7 @@ foreach( dbFetchAll( $sql, false, $params ) as $row ) {
foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile ) foreach ( getSkinIncludes('includes/control_functions.php') as $includeFile )
require_once $includeFile; require_once $includeFile;
$monitor = new Monitor( $mid ); $monitor = new ZM\Monitor($mid);
$focusWindow = true; $focusWindow = true;
@ -60,9 +60,9 @@ xhtmlHeaders(__FILE__, translate('Control') );
</div> </div>
<h2><?php echo translate('Control') ?></h2> <h2><?php echo translate('Control') ?></h2>
<div id="headerControl"> <div id="headerControl">
<form name="contentForm" id="contentForm" method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>"> <form name="contentForm" id="contentForm" method="get" action="?">
<input type="hidden" name="view" value="<?php echo $view ?>"/> <input type="hidden" name="view" value="<?php echo $view ?>"/>
<?php echo buildSelect( "mid", $mids, "this.form.submit();" ); ?> <?php echo buildSelect('mid', $mids, 'this.form.submit();'); ?>
</form> </form>
</div> </div>
</div> </div>

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