Merge branch 'master' into storageareas
Conflicts: docs/installationguide/ubuntu.rst
This commit is contained in:
commit
27597c3401
|
@ -0,0 +1,3 @@
|
||||||
|
img {
|
||||||
|
border: 1px solid black !important;
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
@import url("default.css");
|
|
||||||
|
|
||||||
div.admonition-note {
|
|
||||||
border-top: 2px solid red;
|
|
||||||
border-bottom: 2px solid red;
|
|
||||||
border-left: 2px solid red;
|
|
||||||
border-right: 2px solid red;
|
|
||||||
background-color: #ff6347
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
border: 1px solid black !important;
|
|
||||||
}
|
|
18
docs/conf.py
18
docs/conf.py
|
@ -15,6 +15,9 @@
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.add_stylesheet('zmstyle.css')
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
@ -51,9 +54,9 @@ copyright = u'2014, https://github.com/ZoneMinder/ZoneMinder/graphs/contributors
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '1.28.1'
|
#version = '1.28.1'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '1.28.1'
|
#release = '1.28.1'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
@ -98,14 +101,15 @@ pygments_style = 'sphinx'
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
html_theme = 'default'
|
#html_theme = 'default'
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
html_theme_options = {
|
#html_theme_options = {
|
||||||
"stickysidebar": "true"
|
# "stickysidebar": "true"
|
||||||
}
|
#}
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
#html_theme_path = []
|
#html_theme_path = []
|
||||||
|
@ -130,7 +134,7 @@ html_theme_options = {
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
html_static_path = ['_static']
|
html_static_path = ['_static']
|
||||||
html_style='zmstyles.css'
|
#html_style='zmstyles.css'
|
||||||
|
|
||||||
# Add any extra paths that contain custom files (such as robots.txt or
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
# .htaccess) here, relative to this directory. These files are copied
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
|
|
@ -0,0 +1,477 @@
|
||||||
|
Ubuntu
|
||||||
|
======
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
Easy Way: Install ZoneMinder from a package (Ubuntu 15.x+)
|
||||||
|
-----------------------------------------------------------
|
||||||
|
These instructions are for a brand new ubuntu 15.04 system which does not have ZM installed.
|
||||||
|
|
||||||
|
**Step 1**: Make sure we add the correct packages
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo add-apt-repository ppa:iconnor/zoneminder
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
|
if you don't have mysql already installed:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get install mysql-server
|
||||||
|
|
||||||
|
This will ask you to set up a master password for the DB (you are asked for the mysql root password when installing mysql server).
|
||||||
|
|
||||||
|
**Step 2**: Install ZoneMinder
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get install zoneminder
|
||||||
|
|
||||||
|
**Step 3**: Configure the Database
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
|
||||||
|
mysql -uroot -p -e "grant select,insert,update,delete,create,alter,index,lock tables on zm.* to 'zmuser'@localhost identified by 'zmpass';"
|
||||||
|
|
||||||
|
You don't really need this, but no harm (needed if you are upgrading)
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo /usr/bin/zmupdate.pl
|
||||||
|
|
||||||
|
**Step 4**: Configure systemd to recognize ZoneMinder and configure Apache correctly:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo systemctl enable zoneminder
|
||||||
|
sudo a2enconf zoneminder
|
||||||
|
sudo a2enmod cgi
|
||||||
|
sudo chown -R www-data:www-data /usr/share/zoneminder/
|
||||||
|
|
||||||
|
|
||||||
|
We need this for API routing to work:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo a2enmod rewrite
|
||||||
|
|
||||||
|
This is probably a bug with iconnor's PPA as of Oct 3, 2015 with package 1.28.107. After installing, ``zm.conf`` does not have the right read permissions, so we need to fix that. This may go away in future PPA releases:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo chown www-data:www-data /etc/zm/zm.conf
|
||||||
|
|
||||||
|
We also need to install php5-gd (as of 1.28.107, this is not installed)
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get install php5-gd
|
||||||
|
|
||||||
|
**Step 5**: Edit Timezone in PHP
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
vi /etc/php5/apache2/php.ini
|
||||||
|
|
||||||
|
Look for [Date] and inside it you will see a date.timezone
|
||||||
|
that is commented. remove the comment and specific your timezone.
|
||||||
|
Please make sure the timezone is valid (see this: http://php.net/manual/en/timezones.php)
|
||||||
|
|
||||||
|
In my case:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
date.timezone = America/New_York
|
||||||
|
|
||||||
|
**Step 6**: Restart services
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo service apache2 reload
|
||||||
|
sudo systemctl restart zoneminder
|
||||||
|
|
||||||
|
|
||||||
|
**Step 7: make sure live streaming works**: Make sure you can view Monitor streams:
|
||||||
|
|
||||||
|
startup ZM console in your browser, go to ``Options->Path`` and make sure ``PATH_ZMS`` is set to ``/zm/cgi-bin/nph-zms`` and restart ZM (you should not need to do this for packages, as this should automatically work)
|
||||||
|
|
||||||
|
|
||||||
|
**Step 8**: If you have changed your DB login/password from zmuser/zmpass, the API won't know about it
|
||||||
|
|
||||||
|
If you changed the DB password **after** installing ZM, the APIs will not be able to connect to the DB.
|
||||||
|
|
||||||
|
If you have, go to ``zoneminder/www/api/app/Config`` & Edit ``database.php``
|
||||||
|
|
||||||
|
There is a class there called ``DATABASE_CONFIG`` - change the ``$default`` array to reflect your new details. Example:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
public $default = array(
|
||||||
|
'datasource' => 'Database/Mysql',
|
||||||
|
'persistent' => false,
|
||||||
|
'host' => 'localhost',
|
||||||
|
'login' => 'mynewDBusername',
|
||||||
|
'password' => 'mynewDBpassword'
|
||||||
|
'database' => 'zm',
|
||||||
|
'prefix' => '',
|
||||||
|
//'encoding' => 'utf8',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
You are done. Lets proceed to make sure everything works:
|
||||||
|
|
||||||
|
Making sure ZM and APIs work:
|
||||||
|
|
||||||
|
1. open up a browser and go to ``http://localhost/zm`` - should bring up ZM
|
||||||
|
2. (OPTIONAL - just for peace of mind) open up a tab and go to ``http://localhost/zm/api`` - should bring up a screen showing CakePHP version with some green color boxes. Green is good. If you see red, or you don't see green, there may be a problem (should not happen). Ignore any warnings in yellow saying "DebugKit" not installed. You don't need it
|
||||||
|
3. open up a tab in the same browser and go to ``http://localhost/zm/api/host/getVersion.json``
|
||||||
|
|
||||||
|
If it responds with something like:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
{
|
||||||
|
"version": "1.28.107",
|
||||||
|
"apiversion": "1.28.107.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
**Then your APIs are working**
|
||||||
|
|
||||||
|
Make sure ZM and APIs work with security:
|
||||||
|
1. Enable OPT_AUTH in ZM
|
||||||
|
2. Log out of ZM in browser
|
||||||
|
3. Open a NEW tab in the SAME BROWSER (important) and go to ``http://localhost/zm/api/host/getVersion.json`` - should give you "Unauthorized" along with a lot more of text
|
||||||
|
4. Go to another tab in the SAME BROWSER (important) and log into ZM
|
||||||
|
5. Repeat step 3 and it should give you the ZM and API version
|
||||||
|
|
||||||
|
**Congrats** your installation is complete
|
||||||
|
|
||||||
|
|
||||||
|
Easy Way: Install ZoneMinder from a package (Ubuntu 14.x)
|
||||||
|
-----------------------------------------------------------
|
||||||
|
**These instructions are for a brand new ubuntu 14.x system which does not have ZM installed.**
|
||||||
|
|
||||||
|
**Step 1:** Install ZoneMinder
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo add-apt-repository ppa:iconnor/zoneminder
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install zoneminder
|
||||||
|
|
||||||
|
(just press OK for the prompts you get)
|
||||||
|
|
||||||
|
**Step 2:** Set up DB
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
|
||||||
|
mysql -uroot -p -e "grant select,insert,update,delete,create,alter,index,lock tables on zm.* to 'zmuser'@localhost identified by 'zmpass';"
|
||||||
|
|
||||||
|
**Step 3:** Set up Apache
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo a2enconf zoneminder
|
||||||
|
sudo a2enmod rewrite
|
||||||
|
sudo a2enmod cgi
|
||||||
|
|
||||||
|
**Step 4:**:Some tweaks that will be needed:
|
||||||
|
|
||||||
|
Edit /etc/init.d/zoneminder:
|
||||||
|
|
||||||
|
add a ``sleep 10`` right after line 25 that reads ``echo -n "Starting $prog:"``
|
||||||
|
(The reason we need this sleep is to make sure ZM starts after mysqld starts)
|
||||||
|
|
||||||
|
As of Oct 3 2015, zm.conf is not readable by ZM. This is likely a bug and will go away in the next package
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo chown www-data:www-data /etc/zm/zm.conf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Step 5**: If you have changed your DB login/password
|
||||||
|
|
||||||
|
If you changed the DB password **after** installing ZM, the APIs will not be able to connect to the DB.
|
||||||
|
|
||||||
|
If you have, go to zoneminder/www/api/app/Config & Edit ``database.php``
|
||||||
|
|
||||||
|
There is a class there called ``DATABASE_CONFIG`` - change the ``$default`` array to reflect your new details. Example:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
public $default = array(
|
||||||
|
'datasource' => 'Database/Mysql',
|
||||||
|
'persistent' => false,
|
||||||
|
'host' => 'localhost',
|
||||||
|
'login' => 'mynewDBusername',
|
||||||
|
'password' => 'mynewDBpassword'
|
||||||
|
'database' => 'zm',
|
||||||
|
'prefix' => '',
|
||||||
|
//'encoding' => 'utf8',`
|
||||||
|
);
|
||||||
|
|
||||||
|
We also need to install php5-gd (as of 1.28.107, this is not installed)
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get install php5-gd
|
||||||
|
|
||||||
|
|
||||||
|
**Step 6**: Edit Timezone in PHP
|
||||||
|
|
||||||
|
vi /etc/php5/apache2/php.ini
|
||||||
|
Look for [Date] and inside it you will see a date.timezone
|
||||||
|
that is commented. remove the comment and specific your timezone.
|
||||||
|
Please make sure the timezone is valid (see [this](http://php.net/manual/en/timezones.php))
|
||||||
|
|
||||||
|
In my case:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
date.timezone = America/New_York
|
||||||
|
|
||||||
|
|
||||||
|
**Step 7: make sure live streaming works**: Make sure you can view Monitor streams:
|
||||||
|
|
||||||
|
startup ZM console in your browser, go to ``Options->Path`` and make sure ``PATH_ZMS`` is set to ``/zm/cgi-bin/nph-zms`` and restart ZM (you should not need to do this for packages, as this should automatically work)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
restart:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo service apache2 restart
|
||||||
|
/etc/init.d/zoneminder restart
|
||||||
|
|
||||||
|
**Step 8**: Making sure ZM and APIs work: (optional - only if you need APIs)
|
||||||
|
|
||||||
|
1. open up a browser and go to ``http://localhost/zm`` - should bring up ZM
|
||||||
|
2. (OPTIONAL - just for peace of mind) open up a tab and go to ``http://localhost/zm/api`` - should bring up a screen showing CakePHP version with some green color boxes. Green is good. If you see red, or you don't see green, there may be a problem (should not happen). Ignore any warnings in yellow saying "DebugKit" not installed. You don't need it
|
||||||
|
3. open up a tab in the same browser and go to ``http://localhost/zm/api/host/getVersion.json``
|
||||||
|
|
||||||
|
If it responds with something like:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
{
|
||||||
|
"version": "1.28.107",
|
||||||
|
"apiversion": "1.28.107.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
Then your APIs are working
|
||||||
|
|
||||||
|
Make sure you can view Monitor View:
|
||||||
|
1. Open up ZM, configure your monitors and verify you can view Monitor feeds.
|
||||||
|
2. If not, open up ZM console in your browser, go to ``Options->Path`` and make sure ``PATH_ZMS`` is set to ``/zm/cgi-bin/nph-zms`` and restart ZM (you should not need to do this for packages, as this should automatically work)
|
||||||
|
|
||||||
|
Make sure ZM and APIs work with security:
|
||||||
|
1. Enable OPT_AUTH in ZM
|
||||||
|
2. Log out of ZM in browser
|
||||||
|
3. Open a NEW tab in the SAME BROWSER (important) and go to ``http://localhost/zm/api/host/getVersion.json`` - should give you "Unauthorized" along with a lot more of text
|
||||||
|
4. Go to another tab in the SAME BROWSER (important) and log into ZM
|
||||||
|
5. Repeat step 3 and it should give you the ZM and API version
|
||||||
|
|
||||||
|
**Congrats** Your installation is complete
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Harder Way: Build Package From Source
|
||||||
|
-------------------------------------------
|
||||||
|
(These instructions assume installation from source on a ubuntu 15.x+ system)
|
||||||
|
|
||||||
|
**Step 1:** First make sure you have the needed tools
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install cmake git
|
||||||
|
|
||||||
|
**Step 2:** Next up make sure you have all the dependencies
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo apt-get install apache2 mysql-server php5 php5-mysql build-essential libmysqlclient-dev libssl-dev libbz2-dev libpcre3-dev libdbi-perl libarchive-zip-perl libdate-manip-perl libdevice-serialport-perl libmime-perl libpcre3 libwww-perl libdbd-mysql-perl libsys-mmap-perl yasm automake autoconf libjpeg8-dev libjpeg8 apache2 libapache2-mod-php5 php5-cli libphp-serialization-perl libgnutls-dev libjpeg8-dev libavcodec-dev libavformat-dev libswscale-dev libavutil-dev libv4l-dev libtool ffmpeg libnetpbm10-dev libavdevice-dev libmime-lite-perl dh-autoreconf dpatch policykit-1 libpolkit-gobject-1-dev libextutils-pkgconfig-perl libcurl3 libvlc-dev libcurl4-openssl-dev curl php5-gd
|
||||||
|
|
||||||
|
(you are asked for the mysql root password when installing mysql server - put in a password that you'd like).
|
||||||
|
|
||||||
|
**Step 3:** Download ZoneMinder source code and compile+install:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
git clone https://github.com/ZoneMinder/ZoneMinder.git
|
||||||
|
cd ZoneMinder/
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
cmake .
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
**Step 4:** Now make sure your symlinks to events and images are set correctly:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo ./zmlinkcontent.sh
|
||||||
|
|
||||||
|
**Step 5:** Now lets make sure ZM has DB permissions to write to the DB:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
mysql -uroot -p -e "grant select,insert,update,delete,create,alter,index,lock tables on zm.* to 'zmuser'@localhost identified by 'zmpass';"
|
||||||
|
|
||||||
|
**Step 6:** Now lets create the DB & its tables that ZM needs
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
mysql -uroot -p <db/zm_create.sql
|
||||||
|
|
||||||
|
|
||||||
|
**Step 7:** Now we need to make sure Ubuntu 15 is able to start/stop zoneminder via systemd:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo cp distros/ubuntu1504_cmake/zoneminder.service /lib/systemd/system
|
||||||
|
|
||||||
|
edit **/lib/systemd/system/zoneminder.service** file
|
||||||
|
* rename **/usr/bin/zmpkg** to **/usr/local/bin/zmpkg** everywhere
|
||||||
|
|
||||||
|
(The step above is needed because when you compile from source, it installs to /usr/local/instead of /usr/)
|
||||||
|
|
||||||
|
**Step 8:** Now lets make sure systemd recognizes this file
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable zoneminder.service
|
||||||
|
|
||||||
|
**Step 9:** Now lets work on Zoneminder's apache configuration:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo cp distros/ubuntu1504_cmake/conf/apache2/zoneminder.conf /etc/apache2/conf-available/
|
||||||
|
sudo a2enconf zoneminder
|
||||||
|
sudo a2enmod cgi
|
||||||
|
sudo a2enmod rewrite
|
||||||
|
sudo service apache2 reload
|
||||||
|
|
||||||
|
|
||||||
|
**Step 10:** Edit /etc/apache2/conf-available/zoneminder.conf and change **all** occurrences of:
|
||||||
|
|
||||||
|
* **/usr/lib/zoneminder/cgi-bin** to **/usr/local/libexec/zoneminder/cgi-bin**
|
||||||
|
* **/usr/share/zoneminder** to **/usr/local/share/zoneminder**
|
||||||
|
|
||||||
|
After editing your /etc/apache2/conf-available/zoneminder.conf should look like:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
ScriptAlias /zm/cgi-bin "/usr/local/libexec/zoneminder/cgi-bin"
|
||||||
|
<Directory "/usr/local/libexec/zoneminder/cgi-bin">
|
||||||
|
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
Alias /zm /usr/local/share/zoneminder/www
|
||||||
|
<Directory /usr/local/share/zoneminder/www>
|
||||||
|
php_flag register_globals off
|
||||||
|
Options Indexes FollowSymLinks
|
||||||
|
<IfModule mod_dir.c>
|
||||||
|
DirectoryIndex index.php
|
||||||
|
</IfModule>
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Directory /usr/local/share/zoneminder/www/api>
|
||||||
|
AllowOverride All
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
**Step 11:** Now lets make sure ZM can read/write to the zoneminder directory:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo chown -R www-data:www-data /usr/local/share/zoneminder/
|
||||||
|
|
||||||
|
|
||||||
|
**Step 12:** Make sure you can view Monitor View
|
||||||
|
|
||||||
|
1. Open up ZM, configure your monitors and verify you can view Monitor feeds
|
||||||
|
2. If not, open up ZM console in your browser, go to ``Options->Path`` and make sure ``PATH_ZMS`` is set to ``/zm/cgi-bin/nph-zms`` and restart ZM
|
||||||
|
|
||||||
|
**Step 13**: Edit Timezone in PHP
|
||||||
|
|
||||||
|
vi /etc/php5/apache2/php.ini
|
||||||
|
Look for [Date] and inside it you will see a date.timezone
|
||||||
|
that is commented. remove the comment and specific your timezone.
|
||||||
|
Please make sure the timezone is valid (see http://php.net/manual/en/timezones.php)
|
||||||
|
|
||||||
|
In my case:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
date.timezone = America/New_York
|
||||||
|
|
||||||
|
**Step 14:** Finally, lets make a config change to apache (needed for htaccess overrides to work for APIs)
|
||||||
|
Edit /etc/apache2/apache2.conf and add this:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
<Directory /usr/local/share>
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
Restart apache
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
sudo service apache2 reload
|
||||||
|
|
||||||
|
You are done. Lets proceed to make sure everything works:
|
||||||
|
|
||||||
|
Making sure ZM and APIs work:
|
||||||
|
|
||||||
|
1. open up a browser and go to ``http://localhost/zm`` - should bring up ZM
|
||||||
|
2. (OPTIONAL - just for peace of mind) open up a tab and go to ``http://localhost/zm/api`` - should bring up a screen showing CakePHP version with some green color boxes. Green is good. If you see red, or you don't see green, there may be a problem (should not happen). Ignore any warnings in yellow saying "DebugKit" not installed. You don't need it
|
||||||
|
3. open up a tab in the same browser and go to ``http://localhost/zm/api/host/getVersion.json``
|
||||||
|
|
||||||
|
If it responds with something like:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
{
|
||||||
|
"version": "1.28.107",
|
||||||
|
"apiversion": "1.28.107.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
Then your APIs are working
|
||||||
|
|
||||||
|
Make sure ZM and APIs work with security:
|
||||||
|
1. Enable OPT_AUTH in ZM
|
||||||
|
2. Log out of ZM in browser
|
||||||
|
3. Open a NEW tab in the SAME BROWSER (important) and go to ``http://localhost/zm/api/host/getVersion.json`` - should give you "Unauthorized" along with a lot more of text
|
||||||
|
4. Go to another tab in the SAME BROWSER (important) and log into ZM
|
||||||
|
5. Repeat step 3 and it should give you the ZM and API version
|
||||||
|
|
||||||
|
**Congrats** your installation is complete
|
||||||
|
|
||||||
|
Suggested changes to MySQL (Optional but recommended)
|
||||||
|
------------------------------------------------------
|
||||||
|
For most of you Zoneminder will run just fine with the default MySQL settings. There are a couple of settings that may, in time, provide beneficial especially if you have a number of cameras and many events with a lot of files. One setting we recommend is the "innodb_file_per_table" This will be a default setting in MySQL 5.6 but should be added in MySQL 5.5 which comes with Ubuntu 14.04. A description can be found here: http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html
|
||||||
|
|
||||||
|
To add "innodb_file_per_table" edit the my.cnf file:
|
||||||
|
|
||||||
|
``vi /etc/mysql/my.cnf``
|
||||||
|
Under [mysqld] add
|
||||||
|
``innodb_file_per_table``
|
||||||
|
|
||||||
|
Save and exit.
|
||||||
|
|
||||||
|
Restart MySQL
|
||||||
|
``service mysql restart``
|
||||||
|
|
||||||
|
|
|
@ -357,6 +357,22 @@ our @options =
|
||||||
type => $types{boolean},
|
type => $types{boolean},
|
||||||
category => "system",
|
category => "system",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name => "ZM_OPT_USE_API",
|
||||||
|
default => "yes",
|
||||||
|
description => "Enable ZoneMinder APIs",
|
||||||
|
help => qqq("
|
||||||
|
ZoneMinder now features a new API using which 3rd party
|
||||||
|
applications can interact with ZoneMinder data. It is
|
||||||
|
STRONGLY recommended that you enable authentication along
|
||||||
|
with APIs. Note that the APIs return sensitive data like
|
||||||
|
Monitor access details which are configured as JSON objects.
|
||||||
|
Which is why we recommend you enabling authentication, especially
|
||||||
|
if you are exposing your ZM instance on the Internet.
|
||||||
|
"),
|
||||||
|
type => $types{boolean},
|
||||||
|
category => "system",
|
||||||
|
},
|
||||||
# PP - Google reCaptcha settings
|
# PP - Google reCaptcha settings
|
||||||
{
|
{
|
||||||
name => "ZM_OPT_USE_GOOG_RECAPTCHA",
|
name => "ZM_OPT_USE_GOOG_RECAPTCHA",
|
||||||
|
@ -411,6 +427,7 @@ our @options =
|
||||||
category => "system",
|
category => "system",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
name => "ZM_DIR_EVENTS",
|
name => "ZM_DIR_EVENTS",
|
||||||
default => "events",
|
default => "events",
|
||||||
|
|
|
@ -71,7 +71,7 @@ void RemoteCamera::Initialise()
|
||||||
}
|
}
|
||||||
|
|
||||||
mNeedAuth = false;
|
mNeedAuth = false;
|
||||||
mAuthenticator = new Authenticator(username,password);
|
mAuthenticator = new zm::Authenticator(username,password);
|
||||||
|
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
|
|
@ -50,7 +50,7 @@ protected:
|
||||||
// fill required fields and set needAuth
|
// fill required fields and set needAuth
|
||||||
// subsequent requests can set the required authentication header.
|
// subsequent requests can set the required authentication header.
|
||||||
bool mNeedAuth;
|
bool mNeedAuth;
|
||||||
Authenticator* mAuthenticator;
|
zm::Authenticator* mAuthenticator;
|
||||||
protected:
|
protected:
|
||||||
struct addrinfo *hp;
|
struct addrinfo *hp;
|
||||||
|
|
||||||
|
|
|
@ -306,7 +306,7 @@ int RemoteCameraHttp::GetResponse()
|
||||||
std::string Header = header;
|
std::string Header = header;
|
||||||
|
|
||||||
mAuthenticator->checkAuthResponse(Header);
|
mAuthenticator->checkAuthResponse(Header);
|
||||||
if ( mAuthenticator->auth_method() == AUTH_DIGEST ) {
|
if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) {
|
||||||
Debug( 2, "Need Digest Authentication" );
|
Debug( 2, "Need Digest Authentication" );
|
||||||
request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version );
|
request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version );
|
||||||
request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION );
|
request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION );
|
||||||
|
@ -750,7 +750,7 @@ Debug(3, "Need more data buffer %d < content length %d", buffer.size(), content_
|
||||||
Debug(2, "Checking for digest auth in %s", authenticate_header );
|
Debug(2, "Checking for digest auth in %s", authenticate_header );
|
||||||
|
|
||||||
mAuthenticator->checkAuthResponse(Header);
|
mAuthenticator->checkAuthResponse(Header);
|
||||||
if ( mAuthenticator->auth_method() == AUTH_DIGEST ) {
|
if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) {
|
||||||
Debug( 2, "Need Digest Authentication" );
|
Debug( 2, "Need Digest Authentication" );
|
||||||
request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version );
|
request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version );
|
||||||
request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION );
|
request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION );
|
||||||
|
|
|
@ -203,9 +203,9 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
|
||||||
mNeedAuth = false;
|
mNeedAuth = false;
|
||||||
StringVector parts = split(auth,":");
|
StringVector parts = split(auth,":");
|
||||||
if (parts.size() > 1)
|
if (parts.size() > 1)
|
||||||
mAuthenticator = new Authenticator(parts[0], parts[1]);
|
mAuthenticator = new zm::Authenticator(parts[0], parts[1]);
|
||||||
else
|
else
|
||||||
mAuthenticator = new Authenticator(parts[0], "");
|
mAuthenticator = new zm::Authenticator(parts[0], "");
|
||||||
}
|
}
|
||||||
|
|
||||||
RtspThread::~RtspThread()
|
RtspThread::~RtspThread()
|
||||||
|
|
|
@ -66,7 +66,7 @@ private:
|
||||||
// subsequent requests can set the required authentication header.
|
// subsequent requests can set the required authentication header.
|
||||||
bool mNeedAuth;
|
bool mNeedAuth;
|
||||||
int respCode;
|
int respCode;
|
||||||
Authenticator* mAuthenticator;
|
zm::Authenticator* mAuthenticator;
|
||||||
|
|
||||||
|
|
||||||
std::string mHttpSession; ///< Only for RTSP over HTTP sessions
|
std::string mHttpSession; ///< Only for RTSP over HTTP sessions
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace zm {
|
||||||
|
|
||||||
Authenticator::Authenticator(std::string &username, std::string password) {
|
Authenticator::Authenticator(std::string &username, std::string password) {
|
||||||
#ifdef HAVE_GCRYPT_H
|
#ifdef HAVE_GCRYPT_H
|
||||||
// Special initialisation for libgcrypt
|
// Special initialisation for libgcrypt
|
||||||
|
@ -227,3 +229,5 @@ void Authenticator::checkAuthResponse(std::string &response) {
|
||||||
Debug( 2, "Didn't find auth line in %s", authLine.c_str());
|
Debug( 2, "Didn't find auth line in %s", authLine.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace zm
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
#endif // HAVE_GCRYPT_H || HAVE_LIBCRYPTO
|
#endif // HAVE_GCRYPT_H || HAVE_LIBCRYPTO
|
||||||
|
|
||||||
|
namespace zm {
|
||||||
|
|
||||||
enum AuthMethod { AUTH_UNDEFINED = 0, AUTH_BASIC = 1, AUTH_DIGEST = 2 };
|
enum AuthMethod { AUTH_UNDEFINED = 0, AUTH_BASIC = 1, AUTH_DIGEST = 2 };
|
||||||
class Authenticator {
|
class Authenticator {
|
||||||
public:
|
public:
|
||||||
|
@ -62,4 +64,6 @@ private:
|
||||||
int nc;
|
int nc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace zm
|
||||||
|
|
||||||
#endif // ZM_RTSP_AUTH_H
|
#endif // ZM_RTSP_AUTH_H
|
||||||
|
|
|
@ -34,7 +34,7 @@ class AppController extends Controller {
|
||||||
use CrudControllerTrait;
|
use CrudControllerTrait;
|
||||||
|
|
||||||
public $components = [
|
public $components = [
|
||||||
'Session', // PP - We are going to use SessionHelper to check PHP session vars
|
'Session', // We are going to use SessionHelper to check PHP session vars
|
||||||
'RequestHandler',
|
'RequestHandler',
|
||||||
'Crud.Crud' => [
|
'Crud.Crud' => [
|
||||||
'actions' => [
|
'actions' => [
|
||||||
|
@ -49,7 +49,7 @@ class AppController extends Controller {
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
//PP - Global beforeFilter function
|
// Global beforeFilter function
|
||||||
//Zoneminder sets the username session variable
|
//Zoneminder sets the username session variable
|
||||||
// to the logged in user. If this variable is set
|
// to the logged in user. If this variable is set
|
||||||
// then you are logged in
|
// then you are logged in
|
||||||
|
@ -58,15 +58,63 @@ class AppController extends Controller {
|
||||||
// Also checking to do this only if ZM_OPT_USE_AUTH is on
|
// Also checking to do this only if ZM_OPT_USE_AUTH is on
|
||||||
public function beforeFilter() {
|
public function beforeFilter() {
|
||||||
$this->loadModel('Config');
|
$this->loadModel('Config');
|
||||||
|
|
||||||
|
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_API'));
|
||||||
|
$config = $this->Config->find('first', $options);
|
||||||
|
$zmOptApi = $config['Config']['Value'];
|
||||||
|
|
||||||
|
if ($zmOptApi !='1')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('API Disabled'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH'));
|
$options = array('conditions' => array('Config.' . $this->Config->primaryKey => 'ZM_OPT_USE_AUTH'));
|
||||||
$config = $this->Config->find('first', $options);
|
$config = $this->Config->find('first', $options);
|
||||||
$zmOptAuth = $config['Config']['Value'];
|
$zmOptAuth = $config['Config']['Value'];
|
||||||
if (!$this->Session->Read('user.Username') && ($zmOptAuth=='1'))
|
if (!$this->Session->Read('user.Username') && ($zmOptAuth=='1'))
|
||||||
{
|
{
|
||||||
throw new NotFoundException(__('Not Authenticated'));
|
throw new UnauthorizedException(__('Not Authenticated'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->loadModel('User');
|
||||||
|
$loggedinUser = $this->Session->Read('user.Username');
|
||||||
|
$isEnabled = $this->Session->Read('user.Enabled');
|
||||||
|
// this will likely never happen as if its
|
||||||
|
// not enabled, login will fail and Not Auth will be returned
|
||||||
|
// however, keeping this here for now
|
||||||
|
if ($isEnabled != "1" && $zmOptAuth=="1")
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('User is not enabled'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($zmOptAuth=='1')
|
||||||
|
{
|
||||||
|
$options = array ('conditions' => array ('User.Username' => $loggedinUser));
|
||||||
|
$userMonitors = $this->User->find('first', $options);
|
||||||
|
$this->Session->Write('allowedMonitors',$userMonitors['User']['MonitorIds']);
|
||||||
|
$this->Session->Write('streamPermission',$userMonitors['User']['Stream']);
|
||||||
|
$this->Session->Write('eventPermission',$userMonitors['User']['Events']);
|
||||||
|
$this->Session->Write('controlPermission',$userMonitors['User']['Control']);
|
||||||
|
$this->Session->Write('systemPermission',$userMonitors['User']['System']);
|
||||||
|
$this->Session->Write('monitorPermission',$userMonitors['User']['Monitors']);
|
||||||
|
}
|
||||||
|
else // if auth is not on, you can do everything
|
||||||
|
{
|
||||||
|
//$userMonitors = $this->User->find('first', $options);
|
||||||
|
$this->Session->Write('allowedMonitors','');
|
||||||
|
$this->Session->Write('streamPermission','View');
|
||||||
|
$this->Session->Write('eventPermission','Edit');
|
||||||
|
$this->Session->Write('controlPermission','Edit');
|
||||||
|
$this->Session->Write('systemPermission','Edit');
|
||||||
|
$this->Session->Write('monitorPermission','Edit');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ class ImageComponent extends Component {
|
||||||
$imageFile = $config['ZM_DIR_EVENTS']."/".$imagePath;
|
$imageFile = $config['ZM_DIR_EVENTS']."/".$imagePath;
|
||||||
//$thumbFile = ZM_DIR_EVENTS."/".$thumbPath;
|
//$thumbFile = ZM_DIR_EVENTS."/".$thumbPath;
|
||||||
$thumbFile = $thumbPath;
|
$thumbFile = $thumbPath;
|
||||||
// PP: This segment of code results in errors when trying to get Events API
|
// This segment of code results in errors when trying to get Events API
|
||||||
// This actually seems to be generating images for the angular UI web view
|
// This actually seems to be generating images for the angular UI web view
|
||||||
// and should not be a part of the API anyway
|
// and should not be a part of the API anyway
|
||||||
// I've commented it so events APIs continue to work
|
// I've commented it so events APIs continue to work
|
||||||
|
|
|
@ -15,7 +15,7 @@ class ConfigsController extends AppController {
|
||||||
public $components = array('RequestHandler');
|
public $components = array('RequestHandler');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PP - resolves the issue of not returning all config parameters
|
* resolves the issue of not returning all config parameters
|
||||||
* refer https://github.com/ZoneMinder/ZoneMinder/issues/953
|
* refer https://github.com/ZoneMinder/ZoneMinder/issues/953
|
||||||
* index method
|
* index method
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,6 +14,17 @@ class EventsController extends AppController {
|
||||||
*/
|
*/
|
||||||
public $components = array('RequestHandler', 'Scaler', 'Image', 'Paginator');
|
public $components = array('RequestHandler', 'Scaler', 'Image', 'Paginator');
|
||||||
|
|
||||||
|
public function beforeFilter() {
|
||||||
|
parent::beforeFilter();
|
||||||
|
$canView = $this->Session->Read('eventPermission');
|
||||||
|
if ($canView =='None')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* index method
|
* index method
|
||||||
*
|
*
|
||||||
|
@ -23,6 +34,18 @@ class EventsController extends AppController {
|
||||||
public function index() {
|
public function index() {
|
||||||
$this->Event->recursive = -1;
|
$this->Event->recursive = -1;
|
||||||
|
|
||||||
|
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
if (!empty($allowedMonitors))
|
||||||
|
{
|
||||||
|
$mon_options = array('Event.MonitorId' => $allowedMonitors);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$mon_options='';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($this->request->params['named']) {
|
if ($this->request->params['named']) {
|
||||||
$this->FilterComponent = $this->Components->load('Filter');
|
$this->FilterComponent = $this->Components->load('Filter');
|
||||||
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
$conditions = $this->FilterComponent->buildFilter($this->request->params['named']);
|
||||||
|
@ -39,7 +62,7 @@ class EventsController extends AppController {
|
||||||
$this->Paginator->settings = array(
|
$this->Paginator->settings = array(
|
||||||
// https://github.com/ZoneMinder/ZoneMinder/issues/995
|
// https://github.com/ZoneMinder/ZoneMinder/issues/995
|
||||||
// 'limit' => $limit['ZM_WEB_EVENTS_PER_PAGE'],
|
// 'limit' => $limit['ZM_WEB_EVENTS_PER_PAGE'],
|
||||||
// PP - 25 events per page which is what the above
|
// 25 events per page which is what the above
|
||||||
// default is, is way too low for an API
|
// default is, is way too low for an API
|
||||||
// changing this to 100 so we don't kill ZM
|
// changing this to 100 so we don't kill ZM
|
||||||
// with many event APIs. In future, we can
|
// with many event APIs. In future, we can
|
||||||
|
@ -49,13 +72,13 @@ class EventsController extends AppController {
|
||||||
'limit' => '100',
|
'limit' => '100',
|
||||||
'order' => array('StartTime', 'MaxScore'),
|
'order' => array('StartTime', 'MaxScore'),
|
||||||
'paramType' => 'querystring',
|
'paramType' => 'querystring',
|
||||||
'conditions' => $conditions
|
'conditions' => array (array($conditions, $mon_options))
|
||||||
);
|
);
|
||||||
$events = $this->Paginator->paginate('Event');
|
$events = $this->Paginator->paginate('Event');
|
||||||
|
|
||||||
// For each event, get its thumbnail data (path, width, height)
|
// For each event, get its thumbnail data (path, width, height)
|
||||||
foreach ($events as $key => $value) {
|
foreach ($events as $key => $value) {
|
||||||
// PP - $thumbData = $this->createThumbnail($value['Event']['Id']);
|
//$thumbData = $this->createThumbnail($value['Event']['Id']);
|
||||||
$thumbData = "";
|
$thumbData = "";
|
||||||
$events[$key]['thumbData'] = $thumbData;
|
$events[$key]['thumbData'] = $thumbData;
|
||||||
|
|
||||||
|
@ -71,7 +94,8 @@ class EventsController extends AppController {
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function view($id = null) {
|
public function view($id = null)
|
||||||
|
{
|
||||||
$this->loadModel('Config');
|
$this->loadModel('Config');
|
||||||
$configs = $this->Config->find('list', array(
|
$configs = $this->Config->find('list', array(
|
||||||
'fields' => array('Name', 'Value'),
|
'fields' => array('Name', 'Value'),
|
||||||
|
@ -82,7 +106,19 @@ class EventsController extends AppController {
|
||||||
if (!$this->Event->exists($id)) {
|
if (!$this->Event->exists($id)) {
|
||||||
throw new NotFoundException(__('Invalid event'));
|
throw new NotFoundException(__('Invalid event'));
|
||||||
}
|
}
|
||||||
$options = array('conditions' => array('Event.' . $this->Event->primaryKey => $id));
|
|
||||||
|
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
if (!empty($allowedMonitors))
|
||||||
|
{
|
||||||
|
$mon_options = array('Event.MonitorId' => $allowedMonitors);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$mon_options='';
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = array('conditions' => array(array('Event.' . $this->Event->primaryKey => $id), $mon_options));
|
||||||
$event = $this->Event->find('first', $options);
|
$event = $this->Event->find('first', $options);
|
||||||
|
|
||||||
$path = $configs['ZM_DIR_EVENTS'].'/'.$this->Image->getEventPath($event).'/';
|
$path = $configs['ZM_DIR_EVENTS'].'/'.$this->Image->getEventPath($event).'/';
|
||||||
|
@ -107,12 +143,20 @@ class EventsController extends AppController {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add method
|
* add method
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add() {
|
public function add() {
|
||||||
|
|
||||||
|
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->request->is('post')) {
|
if ($this->request->is('post')) {
|
||||||
$this->Event->create();
|
$this->Event->create();
|
||||||
if ($this->Event->save($this->request->data)) {
|
if ($this->Event->save($this->request->data)) {
|
||||||
|
@ -131,6 +175,13 @@ class EventsController extends AppController {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function edit($id = null) {
|
public function edit($id = null) {
|
||||||
|
|
||||||
|
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->Event->id = $id;
|
$this->Event->id = $id;
|
||||||
|
|
||||||
if (!$this->Event->exists($id)) {
|
if (!$this->Event->exists($id)) {
|
||||||
|
@ -157,15 +208,19 @@ class EventsController extends AppController {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function delete($id = null) {
|
public function delete($id = null) {
|
||||||
|
if ($this->Session->Read('eventPermission') != 'Edit')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
$this->Event->id = $id;
|
$this->Event->id = $id;
|
||||||
if (!$this->Event->exists()) {
|
if (!$this->Event->exists()) {
|
||||||
throw new NotFoundException(__('Invalid event'));
|
throw new NotFoundException(__('Invalid event'));
|
||||||
}
|
}
|
||||||
$this->request->allowMethod('post', 'delete');
|
$this->request->allowMethod('post', 'delete');
|
||||||
if ($this->Event->delete()) {
|
if ($this->Event->delete()) {
|
||||||
// PP - lets make sure the frame table entry is removed too
|
//$this->loadModel('Frame');
|
||||||
$this->loadModel('Frame');
|
//$this->Event->Frame->delete();
|
||||||
$this->Frame->delete();
|
|
||||||
return $this->flash(__('The event has been deleted.'), array('action' => 'index'));
|
return $this->flash(__('The event has been deleted.'), array('action' => 'index'));
|
||||||
} else {
|
} else {
|
||||||
return $this->flash(__('The event could not be deleted. Please, try again.'), array('action' => 'index'));
|
return $this->flash(__('The event could not be deleted. Please, try again.'), array('action' => 'index'));
|
||||||
|
|
|
@ -101,7 +101,10 @@ class HostController extends AppController {
|
||||||
|
|
||||||
function getVersion() {
|
function getVersion() {
|
||||||
$version = Configure::read('ZM_VERSION');
|
$version = Configure::read('ZM_VERSION');
|
||||||
$apiversion = Configure::read('ZM_API_VERSION');
|
// not going to use the ZM_API_VERSION
|
||||||
|
// requires recompilation and dependency on ZM upgrade
|
||||||
|
//$apiversion = Configure::read('ZM_API_VERSION');
|
||||||
|
$apiversion = '1.0';
|
||||||
|
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
'version' => $version,
|
'version' => $version,
|
||||||
|
|
|
@ -16,6 +16,19 @@ class MonitorsController extends AppController {
|
||||||
*/
|
*/
|
||||||
public $components = array('Paginator', 'RequestHandler');
|
public $components = array('Paginator', 'RequestHandler');
|
||||||
|
|
||||||
|
|
||||||
|
public function beforeFilter() {
|
||||||
|
parent::beforeFilter();
|
||||||
|
$canView = $this->Session->Read('monitorPermission');
|
||||||
|
if ($canView =='None')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('Insufficient Privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* index method
|
* index method
|
||||||
*
|
*
|
||||||
|
@ -23,7 +36,17 @@ class MonitorsController extends AppController {
|
||||||
*/
|
*/
|
||||||
public function index() {
|
public function index() {
|
||||||
$this->Monitor->recursive = 0;
|
$this->Monitor->recursive = 0;
|
||||||
$monitors = $this->Monitor->find('all');
|
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
if (!empty($allowedMonitors))
|
||||||
|
{
|
||||||
|
$options = array('conditions'=>array('Monitor.Id'=> $allowedMonitors));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$options='';
|
||||||
|
}
|
||||||
|
$monitors = $this->Monitor->find('all',$options);
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
'monitors' => $monitors,
|
'monitors' => $monitors,
|
||||||
'_serialize' => array('monitors')
|
'_serialize' => array('monitors')
|
||||||
|
@ -42,7 +65,21 @@ class MonitorsController extends AppController {
|
||||||
if (!$this->Monitor->exists($id)) {
|
if (!$this->Monitor->exists($id)) {
|
||||||
throw new NotFoundException(__('Invalid monitor'));
|
throw new NotFoundException(__('Invalid monitor'));
|
||||||
}
|
}
|
||||||
$options = array('conditions' => array('Monitor.' . $this->Monitor->primaryKey => $id));
|
$allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
|
||||||
|
if (!empty($allowedMonitors))
|
||||||
|
{
|
||||||
|
$restricted = array('Monitor.' . $this->Monitor->primaryKey => $allowedMonitors);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$restricted = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = array('conditions' => array(
|
||||||
|
array('Monitor.' . $this->Monitor->primaryKey => $id),
|
||||||
|
$restricted
|
||||||
|
)
|
||||||
|
);
|
||||||
$monitor = $this->Monitor->find('first', $options);
|
$monitor = $this->Monitor->find('first', $options);
|
||||||
$this->set(array(
|
$this->set(array(
|
||||||
'monitor' => $monitor,
|
'monitor' => $monitor,
|
||||||
|
@ -57,6 +94,13 @@ class MonitorsController extends AppController {
|
||||||
*/
|
*/
|
||||||
public function add() {
|
public function add() {
|
||||||
if ($this->request->is('post')) {
|
if ($this->request->is('post')) {
|
||||||
|
|
||||||
|
if ($this->Session->Read('systemPermission') != 'Edit')
|
||||||
|
{
|
||||||
|
throw new UnauthotizedException(__('Insufficient privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->Monitor->create();
|
$this->Monitor->create();
|
||||||
if ($this->Monitor->save($this->request->data)) {
|
if ($this->Monitor->save($this->request->data)) {
|
||||||
$this->daemonControl($this->Monitor->id, 'start', $this->request->data);
|
$this->daemonControl($this->Monitor->id, 'start', $this->request->data);
|
||||||
|
@ -78,7 +122,11 @@ class MonitorsController extends AppController {
|
||||||
if (!$this->Monitor->exists($id)) {
|
if (!$this->Monitor->exists($id)) {
|
||||||
throw new NotFoundException(__('Invalid monitor'));
|
throw new NotFoundException(__('Invalid monitor'));
|
||||||
}
|
}
|
||||||
|
if ($this->Session->Read('systemPermission') != 'Edit')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ($this->Monitor->save($this->request->data)) {
|
if ($this->Monitor->save($this->request->data)) {
|
||||||
$message = 'Saved';
|
$message = 'Saved';
|
||||||
} else {
|
} else {
|
||||||
|
@ -89,9 +137,8 @@ class MonitorsController extends AppController {
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
'_serialize' => array('message')
|
'_serialize' => array('message')
|
||||||
));
|
));
|
||||||
// PP - restart this monitor after change
|
// - restart this monitor after change
|
||||||
$this->daemonControl($this->Monitor->id, 'restart', $this->request->data);
|
$this->daemonControl($this->Monitor->id, 'restart', $this->request->data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,6 +153,11 @@ class MonitorsController extends AppController {
|
||||||
if (!$this->Monitor->exists()) {
|
if (!$this->Monitor->exists()) {
|
||||||
throw new NotFoundException(__('Invalid monitor'));
|
throw new NotFoundException(__('Invalid monitor'));
|
||||||
}
|
}
|
||||||
|
if ($this->Session->Read('systemPermission') != 'Edit')
|
||||||
|
{
|
||||||
|
throw new UnauthorizedException(__('Insufficient privileges'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
$this->request->allowMethod('post', 'delete');
|
$this->request->allowMethod('post', 'delete');
|
||||||
|
|
||||||
$this->daemonControl($this->Monitor->id, 'stop');
|
$this->daemonControl($this->Monitor->id, 'stop');
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
App::uses('AppModel', 'Model');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User Model
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class User extends AppModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use table
|
||||||
|
*
|
||||||
|
* @var mixed False or table name
|
||||||
|
*/
|
||||||
|
public $useTable = 'Users';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary key field
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $primaryKey = 'Id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display field
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $displayField = 'Name';
|
||||||
|
|
||||||
|
}
|
|
@ -910,7 +910,16 @@ $OLANG = array(
|
||||||
"Enable this option to tell ZoneMinder to use this URL. Disable this option to ignore the ".
|
"Enable this option to tell ZoneMinder to use this URL. Disable this option to ignore the ".
|
||||||
"value from the camera and use the value as entered in the monitor configuration~~~~".
|
"value from the camera and use the value as entered in the monitor configuration~~~~".
|
||||||
"Generally this should be enabled. However, there are cases where the camera can get its".
|
"Generally this should be enabled. However, there are cases where the camera can get its".
|
||||||
"own URL incorrect, such as when the camera is streaming through a firewall"
|
"own URL incorrect, such as when the camera is streaming through a firewall"),
|
||||||
|
'OPTIONS_MAXFPS' => array(
|
||||||
|
'Help' => "This field has certain limitations when used for non-local devices.~~ ".
|
||||||
|
"Failure to adhere to these limitations will cause a delay in live video, irregular frame skipping, ".
|
||||||
|
"and missed events~~".
|
||||||
|
"For streaming IP cameras, do not use this field to reduce the frame rate. Set the frame rate in the".
|
||||||
|
" camera, instead. You can, however, use a value that is slightly higher than the frame rate in the camera. ".
|
||||||
|
"In this case, this helps keep the cpu from being overtaxed in the event of a network problem.~~".
|
||||||
|
"Some, mostly older, IP cameras support snapshot mode. In this case ZoneMinder is actively polling the camera ".
|
||||||
|
"for new images. In this case, it is safe to use thie field."
|
||||||
),
|
),
|
||||||
|
|
||||||
// 'LANG_DEFAULT' => array(
|
// 'LANG_DEFAULT' => array(
|
||||||
|
|
|
@ -711,9 +711,19 @@ switch ( $tab )
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><td><?php echo translate('AnalysisFPS') ?></td><td><input type="text" name="newMonitor[AnalysisFPS]" value="<?php echo validHtmlStr($newMonitor['AnalysisFPS']) ?>" size="6"/></td></tr>
|
<tr><td><?php echo translate('AnalysisFPS') ?></td><td><input type="text" name="newMonitor[AnalysisFPS]" value="<?php echo validHtmlStr($newMonitor['AnalysisFPS']) ?>" size="6"/></td></tr>
|
||||||
<tr><td><?php echo translate('MaximumFPS') ?></td><td><input type="text" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($newMonitor['MaxFPS']) ?>" size="6"/></td></tr>
|
|
||||||
<tr><td><?php echo translate('AlarmMaximumFPS') ?></td><td><input type="text" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($newMonitor['AlarmMaxFPS']) ?>" size="6"/></td></tr>
|
|
||||||
<?php
|
<?php
|
||||||
|
if ( $newMonitor['Type'] != "Local" && $newMonitor['Type'] != "File" )
|
||||||
|
{
|
||||||
|
?>
|
||||||
|
<tr><td><?php echo translate('MaximumFPS') ?> (<?php echo makePopupLink('?view=optionhelp&option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" onclick="document.getElementById('newMonitor[MaxFPS]').innerHTML= ' CAUTION: See the help text'" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($newMonitor['MaxFPS']) ?>" size="5"/><span id="newMonitor[MaxFPS]" style="color:red"></span></td></tr>
|
||||||
|
<tr><td><?php echo translate('AlarmMaximumFPS') ?> (<?php echo makePopupLink('?view=optionhelp&option=OPTIONS_MAXFPS', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" onclick="document.getElementById('newMonitor[AlarmMaxFPS]').innerHTML= ' CAUTION: See the help text'" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($newMonitor['AlarmMaxFPS']) ?>" size="5"/><span id="newMonitor[AlarmMaxFPS]" style="color:red"></span></td></tr>
|
||||||
|
<?php
|
||||||
|
} else {
|
||||||
|
?>
|
||||||
|
<tr><td><?php echo translate('MaximumFPS') ?></td><td><input type="text" name="newMonitor[MaxFPS]" value="<?php echo validHtmlStr($newMonitor['MaxFPS']) ?>" size="5"/></td></tr>
|
||||||
|
<tr><td><?php echo translate('AlarmMaximumFPS') ?></td><td><input type="text" name="newMonitor[AlarmMaxFPS]" value="<?php echo validHtmlStr($newMonitor['AlarmMaxFPS']) ?>" size="5"/></td></tr>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
if ( ZM_FAST_IMAGE_BLENDS )
|
if ( ZM_FAST_IMAGE_BLENDS )
|
||||||
{
|
{
|
||||||
?>
|
?>
|
||||||
|
|
Loading…
Reference in New Issue