diff --git a/distros/debian_cmake/links b/distros/debian_cmake/links
index 9f24ba6d1..5560a100a 100644
--- a/distros/debian_cmake/links
+++ b/distros/debian_cmake/links
@@ -1,4 +1,3 @@
var/cache/zoneminder/events usr/share/zoneminder/events
var/cache/zoneminder/images usr/share/zoneminder/images
var/cache/zoneminder/temp usr/share/zoneminder/temp
-usr/lib/zoneminder/cgi-bin usr/share/zoneminder/cgi-bin
diff --git a/distros/ubuntu1204/apache.conf b/distros/ubuntu1204/apache.conf
index 965c67f86..262db423f 100644
--- a/distros/ubuntu1204/apache.conf
+++ b/distros/ubuntu1204/apache.conf
@@ -1,9 +1,21 @@
Alias /zm /usr/share/zoneminder/www
-
- php_flag register_globals off
- Options Indexes FollowSymLinks
-
- DirectoryIndex index.php
-
-
+
+
+ Options +ExecCGI
+ AllowOverride All
+ AddHandler fcgid-script .php
+ FCGIWrapper /usr/bin/php5-cgi
+ Order allow,deny
+ Allow from all
+
+
+
+
+ php_flag register_globals off
+ Options Indexes FollowSymLinks
+
+ DirectoryIndex index.php
+
+
+
diff --git a/distros/ubuntu1504_cmake/zoneminder.postinst b/distros/ubuntu1504_cmake/zoneminder.postinst
index f465bd7ea..82b256e6b 100644
--- a/distros/ubuntu1504_cmake/zoneminder.postinst
+++ b/distros/ubuntu1504_cmake/zoneminder.postinst
@@ -23,7 +23,7 @@ if [ "$1" = "configure" ]; then
zmupdate.pl --nointeractive
else
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
- fi;
+ fi;
fi
diff --git a/docs/_static/zmstyle.css b/docs/_static/zmstyle.css
new file mode 100644
index 000000000..b8f0235f3
--- /dev/null
+++ b/docs/_static/zmstyle.css
@@ -0,0 +1,3 @@
+img {
+ border: 1px solid black !important;
+ }
diff --git a/docs/_static/zmstyles.css b/docs/_static/zmstyles.css
deleted file mode 100644
index 8f59f3910..000000000
--- a/docs/_static/zmstyles.css
+++ /dev/null
@@ -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;
-}
diff --git a/docs/conf.py b/docs/conf.py
index 2d376f03d..109161b24 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -15,6 +15,9 @@
import sys
import os
+def setup(app):
+ app.add_stylesheet('zmstyle.css')
+
# 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
# 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.
#
# The short X.Y version.
-version = '1.28.1'
+#version = '1.28.1'
# 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
# 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
# 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
# further. For a list of options available for each theme, see the
# documentation.
-html_theme_options = {
- "stickysidebar": "true"
-}
+#html_theme_options = {
+# "stickysidebar": "true"
+#}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
@@ -130,7 +134,7 @@ html_theme_options = {
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
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
# .htaccess) here, relative to this directory. These files are copied
diff --git a/docs/installationguide/ubuntu.rst b/docs/installationguide/ubuntu.rst
index b95d46a89..1d5412077 100644
--- a/docs/installationguide/ubuntu.rst
+++ b/docs/installationguide/ubuntu.rst
@@ -1,64 +1,466 @@
Ubuntu
======
-Option A: Install a ready made package
----------------------------------------
+.. contents::
-Installation procedure (common for all versions of Ubuntu)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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.
-It is important that you first apply any system software upgrades first to Ubuntu, especially if you have just created a new image of Ubuntu.
-Not doing this may cause the PPA process to fail and complain about various unmet dependencies.
-
-If you also plan to install the database in the same server (which is typically the case), first do:
+**Step 1**: Make sure we add the correct packages
::
- sudo apt-get install mysql-server
+ sudo add-apt-repository ppa:iconnor/zoneminder
+ sudo apt-get update
-This will ask you for a user and password to configure for Zoneminder.
-Note that when you install the PPA, it will also create a username of zmuser and a password of zmpass irrespective of what you select at this stage
-
-Now add the ppa repository path:
+if you don't have mysql already installed:
::
- sudo apt-add-repository ppa:iconnor/zoneminder
+ 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
-Once you have updated the repository then update and install the package.:
-
::
- sudo apt-get update
- sudo apt-get 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';"
-Post Install steps for Ubuntu 15.x or newer (systemd)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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
- systemctl restart zoneminder
+ sudo systemctl restart zoneminder
-You should now be able to view the zoneminder interface at ``http://localhost/zm`` (replace localhost with your server IP if you are accessing it remotely)
-.. image:: images/zm_first_screen_post_install.png
+**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
-Post install steps for Ubuntu 14.x or older (SystemV)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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
+ Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+ AllowOverride All
+ Require all granted
+
+
+ Alias /zm /usr/local/share/zoneminder/www
+
+ php_flag register_globals off
+ Options Indexes FollowSymLinks
+
+ DirectoryIndex index.php
+
+
+
+
+ AllowOverride All
+
+
+**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:
+
+::
+
+
+ AllowOverride All
+ Require all granted
+
+
+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:
@@ -72,90 +474,4 @@ Save and exit.
Restart MySQL
``service mysql restart``
-Adding a sleep for mysql dependency (Ubuntu 14.x and below only)
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-We recommend you add a "sleep" command just after ``start() {`` in ``/etc/init.d/zoneminder`` to make sure mysql starts before ZoneMinder does. To do this,
-simply modify ``/etc/init.d/zoneminder`` at around line 25 (where you will find the start function) to look like this:
-
-::
-
- start() {
- echo -n "Making sure mysql started... Sleeping for 10 seconds..."
- sleep 10
- echo -n "Starting $prog: "
-
-Making Apache aware of ZoneMinder
-""""""""""""""""""""""""""""""""""""""""""""
-
-Next, we need to make sure apache knows about zoneminder's configuration for apache.
-
-::
-
- ln -s /etc/zm/apache.conf /etc/apache2/conf-available/zoneminder.conf
-
-If you are upgrading from an old version:
-
-::
-
- sudo /usr/bin/zmupdate.pl
-
-Then look for ``/etc/apache2/conf-enable/zm.conf`` - if you have it, please remove it
-
-::
-
- a2enconf zoneminder
- adduser www-data video
-
-
-lets make sure we restart apache:
-
-::
-
- service apache2 restart
-
-
-You should now be able to view the zoneminder interface at ``http://localhost/zm`` (replace localhost with your server IP if you are accessing it remotely)
-
-.. image:: images/zm_first_screen_post_install.png
-
-
-Finally, in the zoneminder web interface, go to Options->Paths, change PATH_ZMS to ``/zm/cgi-bin/nph-zms``
-
-
-Option B: Build Package From Source
--------------------------------------------
-
-A fresh build based on master branch running Ubuntu 1204 LTS. Will likely work for other versions as well.::
-
- root@host:~# aptitude install -y 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-mpm-prefork 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;
-
- root@host:~# git clone https://github.com/ZoneMinder/ZoneMinder.git zoneminder;
- root@host:~# cd zoneminder;
- root@host:~# ln -s distros/ubuntu1204 debian;
- root@host:~# dpkg-checkbuilddeps;
- root@host:~# dpkg-buildpackage;
-
-
-One level above you'll now find a deb package matching the architecture of the build host\:::
-
- root@host:~# ls -1 ~/zoneminder\*;
- /root/zoneminder_1.26.4-1_amd64.changes
- /root/zoneminder_1.26.4-1_amd64.deb
- /root/zoneminder_1.26.4-1.dsc
- /root/zoneminder_1.26.4-1.tar.gz
-
-
-The dpkg command itself does not resolve dependencies. That's what high-level interfaces like aptitude and apt-get are normally for. Unfortunately, unlike RPM, there's no easy way to install a separate deb package not contained with any repository.
-
-To overcome this "limitation" we'll use dpkg only to install the zoneminder package and apt-get to fetch all needed dependencies afterwards. Running dpkg-reconfigure in the end will ensure that the setup scripts e.g. for database provisioning were executed.::
-
- root@host:~# dpkg -i /root/zoneminder_1.26.4-1_amd64.deb; apt-get install -f;
- root@host:~# dpkg-reconfigure zoneminder;
-
-Alternatively you may also use gdebi to automatically resolve dependencies during installation\:::
-
- root@host:~# aptitude install -y gdebi;
- root@host:~# gdebi /root/zoneminder_1.26.4-1_amd64.deb;
-
- 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 libjpeg-turbo8-dev libjpeg-turbo8 apache2-mpm-prefork libapache2-mod-php5 php5-cli
diff --git a/docs/userguide/mobile.rst b/docs/userguide/mobile.rst
index fe8d6e418..b6feb805d 100644
--- a/docs/userguide/mobile.rst
+++ b/docs/userguide/mobile.rst
@@ -3,16 +3,17 @@ Mobile Devices
Here are some options for using ZoneMinder on Mobile devices:
-Using the existing web console
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-* You can directly use the ZoneMinder interface by launching a browser and going to the ZoneMinder server just like you do on the Desktop
-* ZoneMinder also has a "mobile skin" that offers limited functionality (not all views are present in this skin). You can point your mobile browser to ``http://yourzoneminderip/zm/index.php?skin=mobile`` and bookmark it
-
Third party mobile clients
^^^^^^^^^^^^^^^^^^^^^^^^^^^
* zmNinja (`source code `__, needs APIs to be installed to work)
- * Currently in free beta testing for iOS and Android. Will be in app/play store as soon as ZM 1.29 is launched
-* zmView (limited, free) and zmView Pro (more features, paid) - `website `__
+ * Available in App Store and Play Store - `website `__
+* zmView (limited, free) and zmView Pro (more features, paid)
+ * Available in App Store and Play Store, relies on ZM skins `website `__
+
+Using the existing web console
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* You can directly use the ZoneMinder interface by launching a browser and going to the ZoneMinder server just like you do on the Desktop
+* ZoneMinder also has a "mobile skin" that offers limited functionality (not all views are present in this skin). You can point your mobile browser to ``http://yourzoneminderip/zm/index.php?skin=mobile`` and bookmark it. **Note however that 1.29 is the last release that will support the mobile skin. It's use is deprecated**
Discontinued clients
^^^^^^^^^^^^^^^^^^^^
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
index 7fff3d62e..9a065f8cf 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
+++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in
@@ -357,7 +357,23 @@ our @options =
type => $types{boolean},
category => "system",
},
- # PP - Google reCaptcha settings
+ {
+ 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
{
name => "ZM_OPT_USE_GOOG_RECAPTCHA",
default => "no",
@@ -410,6 +426,7 @@ our @options =
type => $types {string},
category => "system",
},
+
{
name => "ZM_DIR_EVENTS",
diff --git a/src/zm_remote_camera.cpp b/src/zm_remote_camera.cpp
index 608311649..8ac4a51ba 100644
--- a/src/zm_remote_camera.cpp
+++ b/src/zm_remote_camera.cpp
@@ -71,7 +71,7 @@ void RemoteCamera::Initialise()
}
mNeedAuth = false;
- mAuthenticator = new Authenticator(username,password);
+ mAuthenticator = new zm::Authenticator(username,password);
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
diff --git a/src/zm_remote_camera.h b/src/zm_remote_camera.h
index 44c00bf65..7e3ae79a8 100644
--- a/src/zm_remote_camera.h
+++ b/src/zm_remote_camera.h
@@ -50,7 +50,7 @@ protected:
// fill required fields and set needAuth
// subsequent requests can set the required authentication header.
bool mNeedAuth;
- Authenticator* mAuthenticator;
+ zm::Authenticator* mAuthenticator;
protected:
struct addrinfo *hp;
diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp
index 44004564f..440c24e05 100644
--- a/src/zm_remote_camera_http.cpp
+++ b/src/zm_remote_camera_http.cpp
@@ -306,7 +306,7 @@ int RemoteCameraHttp::GetResponse()
std::string Header = header;
mAuthenticator->checkAuthResponse(Header);
- if ( mAuthenticator->auth_method() == AUTH_DIGEST ) {
+ if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) {
Debug( 2, "Need Digest Authentication" );
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 );
@@ -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 );
mAuthenticator->checkAuthResponse(Header);
- if ( mAuthenticator->auth_method() == AUTH_DIGEST ) {
+ if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) {
Debug( 2, "Need Digest Authentication" );
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 );
diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp
index 0dbcb7329..7ac80e9b6 100644
--- a/src/zm_rtsp.cpp
+++ b/src/zm_rtsp.cpp
@@ -203,9 +203,9 @@ RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol,
mNeedAuth = false;
StringVector parts = split(auth,":");
if (parts.size() > 1)
- mAuthenticator = new Authenticator(parts[0], parts[1]);
+ mAuthenticator = new zm::Authenticator(parts[0], parts[1]);
else
- mAuthenticator = new Authenticator(parts[0], "");
+ mAuthenticator = new zm::Authenticator(parts[0], "");
}
RtspThread::~RtspThread()
diff --git a/src/zm_rtsp.h b/src/zm_rtsp.h
index acd28e651..192200d0b 100644
--- a/src/zm_rtsp.h
+++ b/src/zm_rtsp.h
@@ -66,7 +66,7 @@ private:
// subsequent requests can set the required authentication header.
bool mNeedAuth;
int respCode;
- Authenticator* mAuthenticator;
+ zm::Authenticator* mAuthenticator;
std::string mHttpSession; ///< Only for RTSP over HTTP sessions
diff --git a/src/zm_rtsp_auth.cpp b/src/zm_rtsp_auth.cpp
index fd9087afa..10ecf3475 100644
--- a/src/zm_rtsp_auth.cpp
+++ b/src/zm_rtsp_auth.cpp
@@ -24,6 +24,8 @@
#include
#include
+namespace zm {
+
Authenticator::Authenticator(std::string &username, std::string password) {
#ifdef HAVE_GCRYPT_H
// 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());
}
}
+
+} // namespace zm
diff --git a/src/zm_rtsp_auth.h b/src/zm_rtsp_auth.h
index 23745f9c7..079dec639 100644
--- a/src/zm_rtsp_auth.h
+++ b/src/zm_rtsp_auth.h
@@ -32,6 +32,8 @@
#include
#endif // HAVE_GCRYPT_H || HAVE_LIBCRYPTO
+namespace zm {
+
enum AuthMethod { AUTH_UNDEFINED = 0, AUTH_BASIC = 1, AUTH_DIGEST = 2 };
class Authenticator {
public:
@@ -62,4 +64,6 @@ private:
int nc;
};
+} // namespace zm
+
#endif // ZM_RTSP_AUTH_H
diff --git a/web/api/app/Controller/AppController.php b/web/api/app/Controller/AppController.php
index 1d85115e8..5b39597b3 100644
--- a/web/api/app/Controller/AppController.php
+++ b/web/api/app/Controller/AppController.php
@@ -34,7 +34,7 @@ class AppController extends Controller {
use CrudControllerTrait;
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',
'Crud.Crud' => [
'actions' => [
@@ -49,7 +49,7 @@ class AppController extends Controller {
]
];
- //PP - Global beforeFilter function
+ // Global beforeFilter function
//Zoneminder sets the username session variable
// to the logged in user. If this variable is set
// then you are logged in
@@ -58,14 +58,62 @@ class AppController extends Controller {
// Also checking to do this only if ZM_OPT_USE_AUTH is on
public function beforeFilter() {
$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'));
$config = $this->Config->find('first', $options);
$zmOptAuth = $config['Config']['Value'];
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;
+ }
+
+ 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');
+ }
+ }
+
}
diff --git a/web/api/app/Controller/Component/ImageComponent.php b/web/api/app/Controller/Component/ImageComponent.php
index 68a254031..f8ed7a533 100644
--- a/web/api/app/Controller/Component/ImageComponent.php
+++ b/web/api/app/Controller/Component/ImageComponent.php
@@ -48,7 +48,7 @@ class ImageComponent extends Component {
$imageFile = $config['ZM_DIR_EVENTS']."/".$imagePath;
//$thumbFile = ZM_DIR_EVENTS."/".$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
// and should not be a part of the API anyway
// I've commented it so events APIs continue to work
diff --git a/web/api/app/Controller/ConfigsController.php b/web/api/app/Controller/ConfigsController.php
index e70978246..48f50ae8e 100644
--- a/web/api/app/Controller/ConfigsController.php
+++ b/web/api/app/Controller/ConfigsController.php
@@ -15,7 +15,7 @@ class ConfigsController extends AppController {
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
* index method
*
diff --git a/web/api/app/Controller/EventsController.php b/web/api/app/Controller/EventsController.php
index 988c19110..ef569cd7b 100644
--- a/web/api/app/Controller/EventsController.php
+++ b/web/api/app/Controller/EventsController.php
@@ -14,6 +14,17 @@ class EventsController extends AppController {
*/
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
*
@@ -22,6 +33,18 @@ class EventsController extends AppController {
*/
public function index() {
$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']) {
$this->FilterComponent = $this->Components->load('Filter');
@@ -39,7 +62,7 @@ class EventsController extends AppController {
$this->Paginator->settings = array(
// https://github.com/ZoneMinder/ZoneMinder/issues/995
// '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
// changing this to 100 so we don't kill ZM
// with many event APIs. In future, we can
@@ -49,14 +72,14 @@ class EventsController extends AppController {
'limit' => '100',
'order' => array('StartTime', 'MaxScore'),
'paramType' => 'querystring',
- 'conditions' => $conditions
+ 'conditions' => array (array($conditions, $mon_options))
);
$events = $this->Paginator->paginate('Event');
// For each event, get its thumbnail data (path, width, height)
foreach ($events as $key => $value) {
- // PP - $thumbData = $this->createThumbnail($value['Event']['Id']);
- $thumbData ="";
+ //$thumbData = $this->createThumbnail($value['Event']['Id']);
+ $thumbData = "";
$events[$key]['thumbData'] = $thumbData;
}
@@ -71,41 +94,55 @@ class EventsController extends AppController {
* @param string $id
* @return void
*/
- public function view($id = null) {
- $this->loadModel('Config');
- $configs = $this->Config->find('list', array(
- 'fields' => array('Name', 'Value'),
- 'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
- ));
+ public function view($id = null)
+{
+ $this->loadModel('Config');
+ $configs = $this->Config->find('list', array(
+ 'fields' => array('Name', 'Value'),
+ 'conditions' => array('Name' => array('ZM_DIR_EVENTS'))
+ ));
- $this->Event->recursive = 1;
- if (!$this->Event->exists($id)) {
- throw new NotFoundException(__('Invalid event'));
- }
- $options = array('conditions' => array('Event.' . $this->Event->primaryKey => $id));
- $event = $this->Event->find('first', $options);
+ $this->Event->recursive = 1;
+ if (!$this->Event->exists($id)) {
+ throw new NotFoundException(__('Invalid event'));
+ }
- $path = $configs['ZM_DIR_EVENTS'].'/'.$this->Image->getEventPath($event).'/';
- $event['Event']['BasePath'] = $path;
+ $allowedMonitors=preg_split ('@,@', $this->Session->Read('allowedMonitors'),NULL, PREG_SPLIT_NO_EMPTY);
- # Get the previous and next events for any monitor
- $this->Event->id = $id;
+ 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);
+
+ $path = $configs['ZM_DIR_EVENTS'].'/'.$this->Image->getEventPath($event).'/';
+ $event['Event']['BasePath'] = $path;
+
+ # Get the previous and next events for any monitor
+ $this->Event->id = $id;
$event_neighbors = $this->Event->find('neighbors');
- $event['Event']['Next'] = $event_neighbors['next']['Event']['Id'];
- $event['Event']['Prev'] = $event_neighbors['prev']['Event']['Id'];
+ $event['Event']['Next'] = $event_neighbors['next']['Event']['Id'];
+ $event['Event']['Prev'] = $event_neighbors['prev']['Event']['Id'];
- # Also get the previous and next events for the same monitor
- $event_monitor_neighbors = $this->Event->find('neighbors', array(
+ # Also get the previous and next events for the same monitor
+ $event_monitor_neighbors = $this->Event->find('neighbors', array(
'conditions'=>array('Event.MonitorId'=>$event['Event']['MonitorId'])
- ));
- $event['Event']['NextOfMonitor'] = $event_monitor_neighbors['next']['Event']['Id'];
- $event['Event']['PrevOfMonitor'] = $event_monitor_neighbors['prev']['Event']['Id'];
+ ));
+ $event['Event']['NextOfMonitor'] = $event_monitor_neighbors['next']['Event']['Id'];
+ $event['Event']['PrevOfMonitor'] = $event_monitor_neighbors['prev']['Event']['Id'];
+
+ $this->set(array(
+ 'event' => $event,
+ '_serialize' => array('event')
+ ));
+ }
- $this->set(array(
- 'event' => $event,
- '_serialize' => array('event')
- ));
- }
/**
* add method
@@ -113,6 +150,13 @@ class EventsController extends AppController {
* @return void
*/
public function add() {
+
+ if ($this->Session->Read('eventPermission') != 'Edit')
+ {
+ throw new UnauthorizedException(__('Insufficient privileges'));
+ return;
+ }
+
if ($this->request->is('post')) {
$this->Event->create();
if ($this->Event->save($this->request->data)) {
@@ -131,6 +175,13 @@ class EventsController extends AppController {
* @return void
*/
public function edit($id = null) {
+
+ if ($this->Session->Read('eventPermission') != 'Edit')
+ {
+ throw new UnauthorizedException(__('Insufficient privileges'));
+ return;
+ }
+
$this->Event->id = $id;
if (!$this->Event->exists($id)) {
@@ -157,15 +208,19 @@ class EventsController extends AppController {
* @return void
*/
public function delete($id = null) {
+ if ($this->Session->Read('eventPermission') != 'Edit')
+ {
+ throw new UnauthorizedException(__('Insufficient privileges'));
+ return;
+ }
$this->Event->id = $id;
if (!$this->Event->exists()) {
throw new NotFoundException(__('Invalid event'));
}
$this->request->allowMethod('post', 'delete');
if ($this->Event->delete()) {
- // PP - lets make sure the frame table entry is removed too
- $this->loadModel('Frame');
- $this->Frame->delete();
+ //$this->loadModel('Frame');
+ //$this->Event->Frame->delete();
return $this->flash(__('The event has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The event could not be deleted. Please, try again.'), array('action' => 'index'));
diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php
index ee5ecd30f..57b210a7e 100644
--- a/web/api/app/Controller/HostController.php
+++ b/web/api/app/Controller/HostController.php
@@ -101,7 +101,10 @@ class HostController extends AppController {
function getVersion() {
$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(
'version' => $version,
diff --git a/web/api/app/Controller/MonitorsController.php b/web/api/app/Controller/MonitorsController.php
index 3aeb31aa8..9ab7461f9 100644
--- a/web/api/app/Controller/MonitorsController.php
+++ b/web/api/app/Controller/MonitorsController.php
@@ -16,6 +16,19 @@ class MonitorsController extends AppController {
*/
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
*
@@ -23,7 +36,17 @@ class MonitorsController extends AppController {
*/
public function index() {
$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(
'monitors' => $monitors,
'_serialize' => array('monitors')
@@ -42,7 +65,21 @@ class MonitorsController extends AppController {
if (!$this->Monitor->exists($id)) {
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);
$this->set(array(
'monitor' => $monitor,
@@ -57,6 +94,13 @@ class MonitorsController extends AppController {
*/
public function add() {
if ($this->request->is('post')) {
+
+ if ($this->Session->Read('systemPermission') != 'Edit')
+ {
+ throw new UnauthotizedException(__('Insufficient privileges'));
+ return;
+ }
+
$this->Monitor->create();
if ($this->Monitor->save($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)) {
throw new NotFoundException(__('Invalid monitor'));
}
-
+ if ($this->Session->Read('systemPermission') != 'Edit')
+ {
+ throw new UnauthorizedException(__('Insufficient privileges'));
+ return;
+ }
if ($this->Monitor->save($this->request->data)) {
$message = 'Saved';
} else {
@@ -89,9 +137,8 @@ class MonitorsController extends AppController {
'message' => $message,
'_serialize' => array('message')
));
- // PP - restart this monitor after change
- $this->daemonControl($this->Monitor->id, 'restart', $this->request->data);
-
+ // - restart this monitor after change
+ $this->daemonControl($this->Monitor->id, 'restart', $this->request->data);
}
/**
@@ -106,6 +153,11 @@ class MonitorsController extends AppController {
if (!$this->Monitor->exists()) {
throw new NotFoundException(__('Invalid monitor'));
}
+ if ($this->Session->Read('systemPermission') != 'Edit')
+ {
+ throw new UnauthorizedException(__('Insufficient privileges'));
+ return;
+ }
$this->request->allowMethod('post', 'delete');
$this->daemonControl($this->Monitor->id, 'stop');
diff --git a/web/api/app/Model/User.php b/web/api/app/Model/User.php
new file mode 100644
index 000000000..8ef18d131
--- /dev/null
+++ b/web/api/app/Model/User.php
@@ -0,0 +1,31 @@
+ 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(
diff --git a/web/skins/classic/js/dark.js b/web/skins/classic/js/dark.js
index 06a940482..f8867feda 100644
--- a/web/skins/classic/js/dark.js
+++ b/web/skins/classic/js/dark.js
@@ -42,8 +42,8 @@ var popupSizes = {
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 100 },
'frames': { 'width': 500, 'height': 600 },
'function': { 'width': 300, 'height': 92 },
- 'group': { 'width': 360, 'height': 180 },
- 'groups': { 'width': 440, 'height': 220 },
+ 'group': { 'width': 360, 'height': 300 },
+ 'groups': { 'width': 540, 'height': 420 },
'image': { 'addWidth': 48, 'addHeight': 80 },
'log': { 'width': 1080, 'height': 720 },
'login': { 'width': 720, 'height': 480 },
diff --git a/web/skins/classic/js/flat.js b/web/skins/classic/js/flat.js
index 2cee14dd2..9b04ca16d 100644
--- a/web/skins/classic/js/flat.js
+++ b/web/skins/classic/js/flat.js
@@ -42,8 +42,8 @@ var popupSizes = {
'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 100 },
'frames': { 'width': 500, 'height': 600 },
'function': { 'width': 300, 'height': 140 },
- 'group': { 'width': 360, 'height': 180 },
- 'groups': { 'width': 440, 'height': 220 },
+ 'group': { 'width': 360, 'height': 300 },
+ 'groups': { 'width': 540, 'height': 420 },
'image': { 'addWidth': 48, 'addHeight': 80 },
'log': { 'width': 1080, 'height': 720 },
'login': { 'width': 720, 'height': 480 },
diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php
index 74249f6ff..e716210ab 100644
--- a/web/skins/classic/views/monitor.php
+++ b/web/skins/classic/views/monitor.php
@@ -694,9 +694,19 @@ switch ( $tab )